MyBatisPlus 注解
半塘 2024/1/14 MyBatisPlus框架
我们在入门案例中用到了@TableName注解,用于绑定数据库表,MyBatisPlus 还提供了很多其他好用的注解,本篇文章将介绍 MyBatisPlus 提供的常用注解。
# 1、@TableName
- 表名注解,标识实体类对应的表
- 使用位置: 实体类
@Data
@TableName("student")
public class StudentPO {
private Long id;
private String name;
private Integer age;
private String email;
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 表名 |
schema | String | 否 | "" | schema |
keepGlobalPrefix | boolean | 否 | false | 是否保持使用全局的 tablePrefix 的值 (当全局 tablePrefix 生效时) |
resultMap | String | 否 | "" | xml 中 resultMap 的 id (用于满足特定类型的实体类对象绑定) |
autoResultMap | boolean | 否 | false | 是否自动构建 resultMap 并使用 (如果设置 resultMap 则不会进行 resultMap 的自动构建与注入) |
excludeProperty | String[] | 否 | {} | 需要排除的属性名 @since 3.3.1 |
- 案例配置
# application.yml
mybatis-plus:
global-config:
db-config:
table-prefix: test. # 配置表前缀
1
2
3
4
5
2
3
4
5
@Data
@TableName(value="student",schema="xygalaxy", keepGlobalPrefix=true,
excludeProperty = {"age"})
public class StudentPO {
private Long id;
private String name;
private Integer age;
private String email;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
- 指定schema为xygalaxy
- keepGlobalPrefix=true时,执行SQL,会自动加上 test.
- excludeProperty={"age"}时,会忽略age属性,不会进行age字段查询,常用于非当前表数据,注意: excludeProperty={"age"}时,不能使用@TableField("age")注解
# 2、@TableId
- 描述: 主键注解
- 使用位置: 实体类主键字段
@Data
@TableName("student")
public class StudentPO {
@TableId
private Long id;
private String name;
private Integer age;
private String email;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 主键字段名 |
type | Enum | 否 | IdType.NONE | 指定主键类型 |
# 2.1、IdType
主键类型可以设置为如下:
值 | 描述 |
---|---|
AUTO | 数据库 ID 自增 |
NONE | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) |
INPUT | insert 前自行 set 主键值 |
ASSIGN_ID | 分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法) |
ASSIGN_UUID | 分配 UUID,主键类型为 String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认 default 方法) |
- 案例说明
@Data
@TableName("student")
public class StudentPO {
@TableId(value = "id",type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
- IdType.AUTO: 数据库字段需要设置自增,否则会报错。
- IdType.INPUT: 新增的数据必须设置id,否则会报错。
- IdType.ASSIGN_ID: 注意数据类型为 Number(Long 和 Integer)或 String),生成结果: 1746460971291541505(Long)
- IdType.ASSIGN_UUID: 主键类型为 String,生成结果: 74d2f31e333483df1f72222e98728900(String)
# 3、@TableField
- 描述: 字段注解(非主键)
@Data
@TableName("student")
public class StudentPO {
private Long id;
@TableField("name")
private String name;
private Integer age;
private String email;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
下面为您展示了这个表格的内容。您可以参考这个表格,对各个属性进行解释。
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 数据库字段名 |
exist | boolean | 否 | true | 是否为数据库表字段 |
condition | String | 否 | "" | 字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s},参考(opens new window) |
update | String | 否 | "" | 字段 update set 部分注入,例如: 当在version字段上注解update="%s+1" 表示更新时会 set version=version+1 (该属性优先级高于 el 属性) |
insertStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例: NOT_NULL insert into table_a( |
updateStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例: IGNORED update table_a set column=#{columnProperty} |
whereStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例: NOT_EMPTY where |
fill | Enum | 否 | FieldFill.DEFAULT | 字段自动填充策略 |
select | boolean | 否 | true | 是否进行 select 查询 |
keepGlobalFormat | boolean | 否 | false | 是否保持使用全局的 format 进行处理 |
jdbcType | JdbcType | 否 | JdbcType.UNDEFINED | JDBC 类型 (该默认值不代表会按照该值生效) |
typeHandler | Class<? extends TypeHandler> | 否 | UnknownTypeHandler.class | 类型处理器 (该默认值不代表会按照该值生效) |
numericScale | String | 否 | "" | 指定小数点后保留的位数 |
- 案例说明
@Data
@TableName(value = "student",excludeProperty = {"age"})
public class StudentPO {
@TableId(value = "id",type = IdType.ASSIGN_UUID)
private Long id;
@TableField(value = "name",condition = SqlCondition.LIKE)
private String name;
private Integer age;
@TableField(exist = false)
private String email;
}
// 测试
@Test
public void testQueryStudentList2(){
StudentPO studentPO = new StudentPO();
studentPO.setName("33");
QueryWrapper<StudentPO> queryWrapper = new QueryWrapper<StudentPO>().setEntity(studentPO);
studentMapper.selectList(queryWrapper).forEach(System.out::println);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
测试结果
- exist效果和excludeProperty一样,建议用exist
- condition 常用在setEntity中生效
# 3.1、FieldStrategy
值 | 描述 |
---|---|
ALWAYS | 总是加入SQL,无论字段值是否为NULL |
NOT_NULL | 非 NULL 判断 |
NOT_EMPTY | 非空判断(只对字符串类型字段,其他类型字段依然为非 NULL 判断) |
DEFAULT | 追随全局配置 |
NEVER | 不加入SQL |
# 3.2、FieldFill
值 | 描述 |
---|---|
DEFAULT | 默认不处理 |
INSERT | 插入时填充字段 |
UPDATE | 更新时填充字段 |
INSERT_UPDATE | 插入和更新时填充字段 |
# 4、@Version
- 描述: 乐观锁注解、标记 @Version 在字段上
@Data
@TableName(value = "student")
public class StudentPO {
private Long id;
private String name;
private Integer age;
private String email;
@Version
private Integer version;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- 乐观锁是一种并发控制策略,通过在数据表中添加一个版本号字段来实现。每次更新数据时,会将版本号加1。当多个用户同时对同一条数据进行修改时,只有一个用户能够成功更新数据,其他用户需要重新读取数据并重新进行修改。这样可以保证数据的一致性。
- 因此,乐观锁字段对于实现乐观锁机制是必要的。如果没有这个字段,就无法实现乐观锁的机制,也就无法保证并发更新时的数据一致性。
# 5、@EnumValue
- 描述: 普通枚举类注解(注解在枚举字段上)
- 单值枚举,可以省略@EnumValue注解,会自动对应上
// 枚举类
public enum SexEnum {
MALE,
FEMALE,
UNKNOWN
}
// 实体类
@Data
@TableName(value = "student")
public class StudentPO {
@TableId(value = "id",type = IdType.ASSIGN_UUID)
private Long id;
private String name;
private Integer age;
private String email;
private SexEnum sex;
private String version;
}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
- 键值类枚举
在需要存储数据库的属性上添加@EnumValue注解,在需要前端展示的属性上添加@JsonValue注解。
@AllArgsConstructor
@Getter
public enum SexEnum {
MAN(1, "男"),
WOMAN(2, "女");
@EnumValue
private Integer key;
@JsonValue
private String display;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
# 6、@TableLogic
- 描述:表字段逻辑处理注解(逻辑删除)
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 逻辑未删除值 |
delval | String | 否 | "" | 逻辑删除值 |
// 实体类
@Data
@TableName(value = "student")
public class StudentPO {
@TableField("is_delete")
@TableLogic(value = "0",delval = "1")
private Integer isDelete;
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 7、@SqlParser
- @SqlParser 注解在多租户的模式下,用来过滤的注解,在最新的 Mybatis Plus 中这个 @SqlParser 注解已经过时。
- 当我们的需要过滤多租户,我们就需要用 @InterceptorIgnore(tenantLine = “1”) 注解来代替。
# 8、@KeySequence
- 描述:序列主键策略 oracle
- 属性:value、dbType
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
value | String | 否 | "" | 序列名 |
dbType | Enum | 否 | DbType.OTHER | 数据库类型,未配置则默认使用 IKeyGenerator 实现,如存在多个实现,必须明确指定 |
@KeySequence(value="seq_user",clazz=String.class) //value为数据库中生成的序列名,class指主键属性类型
public class User {
@TableId(type=IdType.INPUT) //注意主键类型要指定为Input
private String id;
}
1
2
3
4
5
2
3
4
5
Oracle中配合序列使用
序列创建使用
-- 创建序列
CREATE SEQUENCE seq_user
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 10
NOCYCLE
ORDER;
-- seq_user是序列的名称。
-- START WITH指定序列的起始值。
-- INCREMENT BY指定序列的增量值。
-- MINVALUE和MAXVALUE分别指定序列的最小值和最大值。这两个选项是可选的。
-- CACHE指定预分配的序列值的数量,用于提高性能。这个选项也是可选的。
-- ORDER表示生成的序列值是有序的,NOORDER表示生成的序列值是无序的。
-- CYCLE表示当序列达到最大值或最小值时,它会回滚到起始值。
-- NOCYCLE表示当序列达到最大值或最小值时,它将停止生成新的值。
-- 测试序列
SELECT seq_user.NEXTVAL FROM dual;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 9、@InterceptorIgnore
@InterceptorIgnore 用于指定某个方法或类不进行拦截器处理的注解。当你希望某些方法或类不执行拦截器逻辑时,可以使用这个注解。
- value 值为 1 | yes | on 视为忽略,例如 @InterceptorIgnore(tenantLine = "1")
- value 值为 0 | false | off | 空值不变 视为正常执行。
属性名 | 类型 | 默认值 | 描述 |
---|---|---|---|
tenantLine | String | "" | 行级租户 |
dynamicTableName | String | "" | 动态表名 |
blockAttack | String | "" | 攻击 SQL 阻断解析器,防止全表更新与删除 |
illegalSql | String | "" | 垃圾 SQL 拦截 |
- 可以直接标注在方法上或类上。
- 如果标注在方法上,则该方法不会执行任何拦截器逻辑。
- 如果标注在类上,则该类及其所有方法都不会执行拦截器逻辑。
@InterceptorIgnore
public void testMethod() {
// 这个方法不会被任何拦截器处理
}
@InterceptorIgnore
public class TestClass {
public void testMethod() {
// 这个类及其所有方法都不会被任何拦截器处理
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 10、@OrderBy
- 描述:内置 SQL 默认指定排序,优先级低于 wrapper 条件查询
下面的表格以markdown格式呈现:
属性 | 类型 | 必须指定 | 默认值 | 描述 |
---|---|---|---|---|
asc | boolean | 否 | true | 是否倒序查询 |
sort | short | 否 | Short.MAX_VALUE | 数字越小越靠前 |
默认倒序查询
@Data
@TableName(value = "student")
public class StudentPO {
@OrderBy(sort = 1)
@TableId(value = "id",type = IdType.ASSIGN_UUID)
private Long id;
@OrderBy(asc = true,sort = 2)
@TableField(value = "name",condition = SqlCondition.LIKE)
private String name;
private Integer age;
@TableField(exist = false)
private String email;
private SexEnum sex;
@Version
private String version;
@TableField("is_delete")
@TableLogic(value = "0",delval = "1")
private Integer isDelete;
}
// 输出:SELECT id,name,sex,version,is_delete FROM student WHERE is_delete=0 ORDER BY id DESC,name ASC
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
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