MyBatis-Plus 框架详解

MyBatis-Plus 是 MyBatis 的一个插件,它是在 MyBatis 的基础上进行了扩展和增强,目的是简化数据访问层的开发以及提高代码的可维护性,同时也提供了很多便捷的功能。本文将从以下几个方面详细介绍 MyBatis-Plus 框架:

  1. 什么是 MyBatis-Plus
  2. MyBatis-Plus 的优点
  3. MyBatis-Plus 的基本使用
  4. MyBatis-Plus 的高级特性

什么是 MyBatis-Plus

MyBatis-Plus 是一个 MyBatis 的插件,在 MyBatis 的基础上进行了功能扩展和增强。它提供了很多方便的功能,包括但不限于:

  1. 自动生成 MyBatis 的 mapper 接口以及对应的实现类。
  2. 提供了一些通用的 CRUD 方法,如插入、更新、删除、查询等。
  3. 支持 Lambda 表达式查询。
  4. 提供了分页查询的功能。
  5. 支持主键自动生成。
  6. 提供了代码生成器,可以快速生成代码。

MyBatis-Plus 的优点

MyBatis-Plus 的功能强大,且易于使用,具有以下几个优点:

  1. 方便:MyBatis-Plus 可以帮助我们快速生成 MyBatis 的 mapper 接口以及对应的实现类,省去了手写 mapper 接口和 XML 文件的麻烦。
  2. 易用:MyBatis-Plus 提供了很多通用的 CRUD 方法,如插入、更新、删除、查询等,开发者只需要调用这些方法即可完成相应的操作。
  3. 强大:MyBatis-Plus 支持 Lambda 表达式查询、分页查询、主键自动生成等一系列功能。
  4. 可扩展性强:MyBatis-Plus 允许用户通过自定义 MybatisSqlInjector 来扩展 SQL 语句,也允许用户自定义 Condition 类来实现复杂查询。

MyBatis-Plus 的基本使用

集成 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

自动生成 mapper

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);
    }
}

CRUD 操作

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);

Lambda 表达式查询

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 的高级特性

自定义 SQL

MyBatis-Plus 允许用户通过自定义 MybatisSqlInjector 来扩展 SQL 语句,也允许用户自定义 Condition 类来实现复杂查询。

自定义 SQL

我们可以通过定义一个继承 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();

自定义 Condition

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 是一个非常不错的选择。

你可能感兴趣的:(Web,开发框架,Java高级,mybatis,java,spring)