Mybatis-Plus 常用注解总结

在框架的使用中,注解约定大于配置,我们可以轻松通过注解完成很多工作,比如字段改名映射,插入更新的时间写入等,下面的学习内容主要列举了常用的注解。

我们看看官网中列出的注解有哪些[1]:

image.png

本文的注解学习主要内容集中在以下的注解中:

  • @TableName
  • @TableId
  • @TableField
  • @EnumValue
  • @Version
  • @TableLogic

环境:

  • Mybatis-Plus: 3.5.5

@TableName

先看看源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
public @interface TableName {
String value() default "";
String schema() default "";
boolean keepGlobalPrefix() default false;
String resultMap() default "";
boolean autoResultMap() default false;
String[] excludeProperty() default {};
}

开放的功能很多,我们平时可能并用不到,主要需要注意的是 value , 我们通过设置 value = "table_xxx" ,注解加在实体类上,映射实体类和数据库表的表名。

@TableId

源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableId {
String value() default "";
IdType type() default IdType.NONE;
}

注解字段的,通过设置 value 声明在数据库表的字段名,通过 type 属性声明用哪种类型的命名策略,常见的策略有:

image.png

比如我们常用的自增主键,或者通过指定id,默认使用微博开源的雪花算法生成id,全局唯一且自增id,即:

  • @TableId(type = IdType.AUTO)
  • @TableId(type = IdType.ASSIGN_ID)

@TableField

源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface TableField {
String value() default "";
boolean exist() default true;
String condition() default "";
String update() default "";
FieldStrategy insertStrategy() default FieldStrategy.DEFAULT;
FieldStrategy updateStrategy() default FieldStrategy.DEFAULT;
FieldStrategy whereStrategy() default FieldStrategy.DEFAULT;
FieldFill fill() default FieldFill.DEFAULT;
boolean select() default true;
boolean keepGlobalFormat() default false;
String property() default "";
JdbcType jdbcType() default JdbcType.UNDEFINED;
Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;
boolean javaType() default false;
String numericScale() default "";
}

该注解提供的功能很多,这里讲几个常用的。

value

通过设置该值,对应到数据库表的字段名。

condition

设定值,进而是否开启如模糊查询。

exist

主要指明字段在不在数据库表中,如果 false 则不在数据库表中。

select

注明查到的字段是否要出现在返回结果中,某些场景中,如 User 表中,可能有 password ,对于这种敏感的字段,是不是可以不用返回呢。

fill

这里涉及自动填充,在哪些场景中会用到呢,如 插入、更新、更改的时间,我们希望自动填入,其原理其实也是通过设置实体的值,进而达到自动填入的功能。

填入时机:

image.png

如果设置了该 fill 属性,则我们需要去实现或者继承 MetaObjectHandler 接口:

package com.example.springbootmybatisplusdemo.config;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
import java.time.LocalDateTime;
@Configuration
@MapperScan(basePackages = "com.example.springbootmybatisplusdemo.mapper")
public class AutoTimeConfig implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// method 1
this.strictInsertFill(metaObject, "created", () -> LocalDateTime.now(), LocalDateTime.class);
this.strictInsertFill(metaObject, "modified", () -> LocalDateTime.now(), LocalDateTime.class);
// method 2
// setFieldValByName("created", LocalDateTime.now(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updated", () -> LocalDateTime.now(), LocalDateTime.class);
}
}

在上面的实现中,我们实现了 insertFill/updateFill 两个方法,另外对于字段值的填充,在代码中也注明了2种方法。

@EnumValue

源码:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
public @interface EnumValue {
}

这里的使用上,我们需要加到会在数据库表中显示的字段上,比如我们的实体类:

private GenderEnum gender;

GenderEnum 是一个枚举类:

package com.example.springbootmybatisplusdemo.entity;
import com.baomidou.mybatisplus.annotation.EnumValue;
public enum GenderEnum {
Male(1, "Male"),
Female(0, "Female");
@EnumValue
private final int code;
private final String desc;
GenderEnum(int code, String desc) {
this.code = code;
this.desc = desc;
}
}

通过上述的配置,我们就可以在设置 gender 字段时,通过 GenderEnum 枚举类给定 Male或者Female,最后写入数据库表时,实际是写入的 code 的值,注意我们声明的 1 -> Male,0 -> Female,所以在数据库表中,gender 实际填入的值是 0/1

@Value

该注解主要用于乐观锁,结合拦截件使用:

package com.example.springbootmybatisplusdemo.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = "com.example.springbootmybatisplusdemo.mapper")
public class MybatisPlusConfig {
// register 乐观锁插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}

测试:

package com.example.springbootmybatisplusdemo.test;
import com.example.springbootmybatisplusdemo.entity.UserDemo;
import com.example.springbootmybatisplusdemo.mapper.UserDemoMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class optimisticLockTest {
@Autowired
private UserDemoMapper userMapper;
@Test
public void lockTest() {
UserDemo user1 = new UserDemo();
user1.setId(100L);
user1.setVersion(1);
UserDemo user2 = new UserDemo();
user2.setId(100L);
user2.setVersion(1);
userMapper.updateById(user1); // ok
userMapper.updateById(user2); // fail
}
}

@TableLogic

该注解用于逻辑删除,真删除是删除数据库表中的记录行,逻辑删除则是标记某个字段的值,如:

@TableLogic(value = "0", delval = "1")
private Integer deleted;

其中 value 是原值,delval 是删除后填入的值,如删除前,deleted为0,删除后deleted为1,我们在查询数据时注意下这个字段即可。

demo

以下是以上注解在 case 中的使用:

package com.example.springbootmybatisplusdemo.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName(value = "user_demo") // tableName
public class UserDemo {
@TableId(type = IdType.AUTO) // tableId,自增类型,主键
private Long id;
@TableId(type = IdType.ASSIGN_ID) // 该策略使用接口IdentifierGenerator的方法nextId(以实现类为DefaultIdentifierGenerator雪花算法)
private Long myId;
@TableField(value = "name", condition = SqlCondition.LIKE) // tableField,开启模糊查询
private String username;
@TableField(exist = false) // 指明字段不在数据表中
private String username1;
@TableField(select = false) // 字段不出现在返回结果中
private String password;
@TableField(fill = FieldFill.INSERT) // 如果继承接口,已经实现了insertFill,需要实现 MetaObjectHandler,见AutoTimeConfig
private LocalDateTime created;
@TableField(fill = FieldFill.UPDATE) // 需要实现 MetaObjectHandler
private LocalDateTime updated;
@TableField(fill = FieldFill.INSERT_UPDATE) // 需要实现 MetaObjectHandler
private LocalDateTime modified;
private GenderEnum gender; // enumValue
@Version
private Integer version; // version,乐观锁,集合配置使用,如拦截件
@TableLogic(value = "0", delval = "1") // 逻辑删除,其实就是更新delete字段的值,0 -> 1, update table_name set deleted=1 where xxx=yyy, or delete from table_name where xxx=yyy
private Integer deleted;
}

参考:

posted on   进击的davis  阅读(920)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2020-12-28 linux 常用命令大全
2020-12-28 linux tar包安装sqlite3

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示