MybatisPlus映射问题

MybatisPlus框架下属性与表名的映射设置与常用的注解。

属性对应问题

我在实体类与数据库表属性对应时发现一个问题:在实体类属性和数据库表属性都是user_id时,MybatisPlus能够从数据库表中查询到user_id的数值,但是无法将这个数值反馈给我的实体类属性。

考虑到可能是属性名对应失败,我在application配置文件中将MybatisPlus的驼峰关闭,属性成功对应上了。

这是因为MybatisPlus默认开启驼峰命名法,即按规则数据表中的lastName字段应对应实体类中的last_name属性,而实体类中的lastName属性应对应数据表中的last_name字段。

那么便出现了几点疑问了:

  1. MybatisPlus默认支持的是属性名完全相同的对应方式,还是实体类驼峰+数据库表下划线的搭配方式?
  2. 什么时候需要在配置文件中开启驼峰,什么时候需要进行关闭?

默认驼峰命名

简单的属性就是实体类和数据库表进行对应就行,就是一个单词,和驼峰不沾关系。比如username对应username,phone对应phone当多属性组合名称出现时,比如user_id,MybatisPlus默认支持的是实体类驼峰+数据库表下划线的对应形式。下面我们只对多属性组合名称出现时的情况进行考虑。

Mybatis Plus默认是支持驼峰命名的。Mybatis Plus会自动将Java类属性名与数据库表字段名进行匹配,并生成对应的SQL语句。

在Mybatis Plus中,默认情况下会启用驼峰命名规则。也就是说,在实体类中定义的属性名使用驼峰命名方式,而在数据库表中定义的列名使用下划线方式,Mybatis Plus会自动将它们映射起来,无需再写额外的映射配置。

举个例子,假设我们有一个User实体类:

1
2
3
4
5
public class User {
private Long id;
private String userName;
private Integer age;
}

如果我们使用默认的Mybatis Plus配置,那么在进行CRUD操作时,Mybatis Plus会自动将Java类的属性名与数据库表的列名进行匹配,例如:

  • 查询用户信息
    1
    SELECT id, user_name, age FROM user WHERE id = #{id}
  • 新增用户信息
    1
    INSERT INTO user (id, user_name, age) VALUES (#{id}, #{userName}, #{age})
  • 修改用户信息
    1
    UPDATE user SET user_name = #{userName}, age = #{age} WHERE id = #{id}

关闭全局驼峰

当我们的实体类属性和数据库属性都是下划线的命名形式时,我们可以关闭驼峰。

1
2
3
4
5
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
# 关闭驼峰映射
map-underscore-to-camel-case: false

关闭部分驼峰

如果我想让驼峰形式的实体类名与下划线形式的数据库表名进行对应,但是不想让驼峰形式的实体类属性与下划线形式的数据库表属性进行对应,可以在 MybatisPlus 的全局配置文件中设置相应的命名策略和映射策略。

1
2
3
4
5
6
7
8
9
mybatis-plus:
global-config:
# 实体类命名策略
db-config:
table-underline: true
# 数据库表名映射策略
meta-object-handler:
field-strategy: not_empty
name-convert: com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator

其中,mybatis-plus.global-config.db-config.table-underline 表示数据库表名的下划线映射策略,将它设置为 true 即可启用下划线命名策略;mybatis-plus.global-config.meta-object-handler.name-convert 表示实体类名称的命名策略,将它设置为 com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator 就可以实现实体类中的驼峰类名与数据库表中下划线命名的表名自动对应。这样就可以达到想要的效果。

需要注意的是,此时实体类属性名和数据库表字段名仍然需要手动设置映射关系。可以使用 @TableField 注解手动指定属性名与字段名的映射关系,例如:

1
2
3
4
5
public class User {
@TableField(value = "user_id")
private Long userId;
// 其他属性...
}

常用注解

1、@TableName表名映射

实体类与数据库表进行对应

MybatisPlus中的@Tablename注解同样是用于指定实体类对应的数据库表名的。在使用MybatisPlus进行数据持久化操作时,如果实体类名称与对应的数据库表名不一致,则需要使用@Tablename注解来显式地指定表名。例如,在实体类上添加@Tablename(“user”)注解,则该实体类对应的数据库表名为”user”。

1
2
3
4
5
6
7
@Tablename("user")
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}

需要注意的是,MybatisPlus中的@Tablename注解位于com.baomidou.mybatisplus.annotation包下,而非javax.persistence包下。虽然两者的功能相似,但是MybatisPlus中的@Tablename注解是针对MybatisPlus框架设计的,与JPA规范并不完全一致,因此在使用时需要注意区分。

2、@TableId主键策略

声明主键策略

@TableId注解是MybatisPlus框架中用于标识实体类主键的注解。在一张数据库表中,每个记录都应该有一个唯一的主键来标识该记录,@TableId注解就是用来指定实体类中哪个属性对应数据库表的主键。

@TableId注解有两种使用方式:

  1. 针对单一主键:在实体类对应主键字段上添加@TableId注解即可,例如:@TableId(“id”)

写法:@TableId(value=“数据库主键字段”,type = IdType.六种类型之一)

1
2
3
4
5
6
7
8
public enum IdType {
AUTO, //数据库id自增
INPUT, //手动输入
ID_WORKER, //默认的全局唯一id
UUID, //全局唯一id uuid
NONE;//未设置主键
**
}

实体类使用实例

1
2
3
4
5
6
7
8
9
10
11
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
//设置主键自增
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
}

数据库字段一定配置同时自增

  1. 针对联合主键:在实体类中将所有联合主键字段组成一个对象并添加对应的@TableId注解,例如:
1
2
3
4
5
6
public class User implements Serializable {
@TableId(type = IdType.INPUT)
private Long tenantId;
@TableId(type = IdType.AUTO)
private Long id;
}

其中,type属性指定主键生成策略,IdType枚举类型提供了多种可选策略,例如INPUT、AUTO、ID_WORKER等。如果不指定值,则使用MybatisPlus的默认策略。

3、@TableField属性对应与忽略

属性名称对应、属性忽略

使用MybatisPlus框架时,会存在实体类属性和数据库表属性不对应的情况。这种情况下,查询操作可能会出现查不出数据的情况。

为了避免这种情况,我们需要手动设置实体类属性与数据库表属性的映射关系,可以使用注解或者配置文件来实现。具体来说,可以在实体类中使用@TableField注解指定数据库表中的列名,或者在MybatisPlus的全局配置文件中配置属性名与列名的映射关系。

1
2
3
//指定属性所对应的字段名
@TableField("user_name")
private String name;

项目中的SQL全部由Mybatis-Plus自动生成,MP会根据实体类对于SQL语句进行生成,实体类中有个字段在数据库不需要,但项目中需要使用,可以通过添加注解忽略掉该字段

@TableField(exist = false):表示该属性不为数据库表字段,但又是必须使用的。

1
2
3
//指定属性所对应的字段名
@TableField(exist = false)
private User user;

@TableField(exist = true):表示该属性为数据库表字段。

通过此注解enable字段便不再生成到SQL语句中。

4、@TableLogic软删除

逻辑删除

@TableLogic注解是MybatisPlus框架中用于标识逻辑删除属性的注解。在一些业务场景下,需要对数据进行软删除而不是物理删除,这时就可以使用逻辑删除来实现。@TableLogic注解就是用来指定实体类中哪个属性是逻辑删除属性。

@TableLogic注解只需要添加到实体类对应的逻辑删除字段上即可,例如:

1
2
3
4
5
6
7
8
public class User implements Serializable {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
@TableLogic
private Integer deleted;
}

其中,@TableLogic注解表示deleted字段是逻辑删除字段。默认情况下,MybatisPlus将值为1的记录视为已删除状态,0或null的记录视为未删除状态。如果需要修改删除状态值,则可以通过全局配置或局部配置的方式进行设置。


MybatisPlus的逻辑删除实现非常简单,可以通过以下步骤来实现:

  1. 在数据库表中添加一个字段用于标识数据是否被删除(例如命名为deleted或is_deleted),并设置默认值为0。
  2. 在实体类中添加一个与逻辑删除字段对应的属性,并在该属性上添加@TableLogic注解。
  3. 配置全局的逻辑删除属性和逻辑未删除属性的值。这一步是可选的,如果不进行配置,则使用MybatisPlus默认的删除状态值(已删除为1,未删除为0)。

下面是一个简单的示例:

  1. 数据库表结构:
1
2
3
4
5
6
7
CREATE TABLE user (
id BIGINT(20) NOT NULL AUTO_INCREMENT,
name VARCHAR(50) DEFAULT NULL,
age INT(11) DEFAULT NULL,
deleted TINYINT(4) DEFAULT '0',
PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
  1. 实体类:
1
2
3
4
5
6
7
8
public class User implements Serializable {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
@TableLogic(value = "0", delval = "1")
private Integer deleted;
}
  1. MybatisPlus配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Configuration
@MapperScan("com.example.mapper")
public class MybatisPlusConfig {

@Bean
public LogicSqlInjector logicSqlInjector() {
return new LogicSqlInjector();
}

@Bean
public GlobalConfig globalConfig() {
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setLogicDeleteValue("1");
globalConfig.setLogicNotDeleteValue("0");
return globalConfig;
}

}

在上面的示例中,我们通过@TableLogic注解将User实体类中deleted字段标识为逻辑删除字段。同时,在MybatisPlus配置中使用了LogicSqlInjector插件和GlobalConfig对象来分别设置逻辑删除SQL注入器和删除状态值。

有了这些配置之后,就可以在Mapper接口中使用MybatisPlus提供的逻辑删除方法进行软删除操作了,例如:

1
2
3
4
5
6
7
public interface UserMapper extends BaseMapper<User> {

@Override
@TableLogic
int deleteById(Serializable id);

}

在调用deleteById方法时,MybatisPlus会自动附加逻辑删除的条件(即deleted=0),并执行update语句将对应记录的deleted字段的值更新为1,实现了软删除的功能。


MybatisPlus映射问题
http://wahoyu.xyz/2023/03/01/MybatisPlusMapper/
作者
Wahoyu
发布于
2023年3月1日
许可协议