MyBatis-Plus 是 MyBatis 的一个插件,它是在 MyBatis 的基础上进行了扩展和增强,目的是简化数据访问层的开发以及提高代码的可维护性,同时也提供了很多便捷的功能。本文将从以下几个方面详细介绍 MyBatis-Plus 框架:
MyBatis-Plus 是一个 MyBatis 的插件,在 MyBatis 的基础上进行了功能扩展和增强。它提供了很多方便的功能,包括但不限于:
MyBatis-Plus 的功能强大,且易于使用,具有以下几个优点:
要使用 MyBatis-Plus,我们首先需要将它集成到我们的项目中。我们可以在我们的 Maven 或 Gradle 项目中添加以下依赖:
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>{latest.version}version>
dependency>
或者
dependencies {
implementation 'com.baomidou:mybatis-plus-boot-starter:{latest.version}'
}
然后在 Spring Boot 的配置文件中添加以下配置:
mybatis-plus:
mapper-locations: classpath:/mapper/*.xml
MyBatis-Plus 可以帮助我们自动生成 mapper 接口和 XML 文件。我们只需要定义一个继承 BaseMapper 的接口,然后在启动类上添加 @MapperScan 注解即可。例如:
public interface UserMapper extends BaseMapper<User> {
// ...
}
@SpringBootApplication
@MapperScan("com.example.demo.mapper")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
MyBatis-Plus 提供了很多通用的 CRUD 方法,如插入、更新、删除、查询等。
MyBatis-Plus 提供了 insert、insertBatch、insertOrUpdate 等多个插入方法。例如:
User user = new User();
user.setName("Tom");
user.setAge(18);
userMapper.insert(user);
MyBatis-Plus 提供了 deleteById、delete、deleteBatchIds 等多个删除方法。例如:
userMapper.deleteById(1L);
MyBatis-Plus 提供了 updateById、update、updateBatchById 等多个更新方法。例如:
User user = new User();
user.setId(1L);
user.setName("Jerry");
userMapper.updateById(user);
MyBatis-Plus 提供了很多查询方法,包括根据 ID 查询、根据条件查询、分页查询等。例如:
User user = userMapper.selectById(1L);
List<User> userList = userMapper.selectList(null);
MyBatis-Plus 还支持使用 Lambda 表达式进行查询,可以让我们更加方便地进行条件查询。例如:
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
.eq(User::getName, "Tom")
.ge(User::getAge, 18);
List<User> userList = userMapper.selectList(wrapper);
MyBatis-Plus 提供了分页查询的功能,可以方便地进行分页操作。例如:
IPage<User> page = new Page<>(1, 10);
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
.eq(User::getName, "Tom")
.ge(User::getAge, 18);
IPage<User> userPage = userMapper.selectPage(page, wrapper);
List<User> userList = userPage.getRecords();
MyBatis-Plus 还提供了代码生成器,可以帮助我们快速生成 mapper 接口、XML 文件以及实体类等。我们只需要在控制台中输入相关命令即可生成代码。例如:
mvn mybatis-plus:generator
MyBatis-Plus 允许用户通过自定义 MybatisSqlInjector 来扩展 SQL 语句,也允许用户自定义 Condition 类来实现复杂查询。
我们可以通过定义一个继承 AbstractMethod 的类来自定义 SQL 操作,例如:
public class SelectAll extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String sql = "SELECT * FROM " + tableInfo.getTableName();
SqlSource sqlSource = new RawSqlSource(configuration, sql, modelClass);
return this.addSelectMappedStatement(mapperClass, "selectAll", sqlSource, modelClass, tableInfo);
}
}
然后在我们的 Mapper 上使用 @SqlParser 注解即可:
@SqlParser(method = "selectAll", type = SqlType.SELECT)
List<User> selectAll();
MyBatis-Plus 提供了方便的 Condition 类来实现复杂查询。我们可以通过继承 AbstractWrapper 或者 QueryWrapper 来实现自己的 Condition 类。
例如:
public class UserCondition extends QueryWrapper<User> {
public UserCondition() {
super();
}
public UserCondition nameLike(String value) {
if (StringUtils.isNotBlank(value)) {
this.like(User::getName, value);
}
return this;
}
public UserCondition ageGt(Integer value) {
if (value != null) {
this.gt(User::getAge, value);
}
return this;
}
}
然后我们就可以通过使用 UserCondition 来实现复杂查询,例如:
UserCondition condition = new UserCondition()
.nameLike("Tom")
.ageGt(18);
List<User> userList = userMapper.selectList(condition);
有时候我们需要根据运行时的情况动态指定表名,MyBatis-Plus 提供了方便的功能来实现动态表名。
例如:
String tableName = "user_2023";
MappedStatement ms = sqlSession
.getConfiguration()
.getMappedStatement("com.example.demo.mapper.UserMapper.selectById");
// 通过反射修改 MappedStatement 中的 sqlSource
Field sqlSourceField = ms.getClass().getDeclaredField("sqlSource");
sqlSourceField.setAccessible(true);
SqlSource sqlSource = (SqlSource) sqlSourceField.get(ms);
if (sqlSource instanceof DynamicSqlSource) {
Field rootSqlNodeField = DynamicSqlSource.class.getDeclaredField("rootSqlNode");
rootSqlNodeField.setAccessible(true);
SqlNode sqlNode = (SqlNode) rootSqlNodeField.get(sqlSource);
if (sqlNode instanceof MixedSqlNode) {
List<SqlNode> contents = ((MixedSqlNode) sqlNode).getContents();
for (int i = 0; i < contents.size(); i++) {
SqlNode item = contents.get(i);
if (item instanceof StaticTextSqlNode) {
String originalSql = ((StaticTextSqlNode) item).getText();
// 修改 SQL 语句中的表名
String newSql = originalSql.replaceAll("user", tableName);
contents.set(i, new StaticTextSqlNode(newSql));
break;
}
}
}
// 重新生成 SQLSource
Configuration configuration = sqlSession.getConfiguration();
LanguageDriver languageDriver = configuration.getDefaultScriptingLanguageInstance();
sqlSource = languageDriver.createSqlSource(configuration, sqlNode, null);
sqlSourceField.set(ms, sqlSource);
}
User user = userMapper.selectById(1L);
MyBatis-Plus 还提供了方便的实现乐观锁的功能。
在表中增加一个版本号字段 version,然后在实体类中添加 @Version 注解即可:
@Data
public class User {
private Long id;
private String name;
private Integer age;
@Version
private Integer version;
}
然后在更新操作中,MyBatis-Plus 会自动检查 version 字段,如果发现 version 发生变化,则会抛出 OptimisticLockException 异常:
User user = userMapper.selectById(1L);
user.setName("Jerry");
userMapper.updateById(user);
MyBatis-Plus 还提供了方便的自动填充功能,可以在数据插入和修改的时候自动填充一些字段,例如创建时间、更新时间等。
我们需要定义一个继承 MetaObjectHandler 的类,并重写其两个方法:
@Component
public class MyMetaObjectHandler extends MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
Date now = new Date();
this.setFieldValByName("createTime", now, metaObject);
this.setFieldValByName("updateTime", now, metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
Date now = new Date();
this.setFieldValByName("updateTime", now, metaObject);
}
}
然后在实体类中添加相应的注解即可:
@Data
@TableName("user")
public class User {
private Long id;
private String name;
private Integer age;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
MyBatis-Plus 是一个强大且易于使用的 MyBatis 插件,它提供了很多方便的功能,包括自动生成 mapper、通用的 CRUD 方法、Lambda 表达式查询、分页查询、代码生成器等。同时,它还提供了一些高级特性,如自定义 SQL、乐观锁、自动填充等。因此,在开发数据访问层时,使用 MyBatis-Plus 是一个非常不错的选择。