Mybatis-Plus 常用注解总结
在框架的使用中,注解约定大于配置,我们可以轻松通过注解完成很多工作,比如字段改名映射,插入更新的时间写入等,下面的学习内容主要列举了常用的注解。
我们看看官网中列出的注解有哪些[1]:
本文的注解学习主要内容集中在以下的注解中:
- @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
属性声明用哪种类型的命名策略,常见的策略有:
比如我们常用的自增主键,或者通过指定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
这里涉及自动填充,在哪些场景中会用到呢,如 插入、更新、更改的时间,我们希望自动填入,其原理其实也是通过设置实体的值,进而达到自动填入的功能。
填入时机:
如果设置了该 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; }
参考:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有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