MyBatis-Plus高效开发实战

概述

MyBatis-Plus 是 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,简化开发、提高效率。本文将介绍 MyBatis-Plus 的几个核心功能在实际项目中的应用

条件构造器

MyBatis-Plus 提供了强大的条件构造器 Wrapper,可以方便地构建复杂的查询条件。如下:

基本查询

java 复制代码
// 查询用户名包含a,年龄在20到30之间,并且邮箱不为null的用户信息
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("username", "a")
        .between("age", 20, 30)
        .isNotNull("email");
List<User> list = userMapper.selectList(queryWrapper);

排序查询

java 复制代码
// 按年龄降序查询用户,如果年龄相同则按id升序排列
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("age").orderByAsc("id");
List<User> users = userMapper.selectList(queryWrapper);

Lambda 表达式

使用 Lambda 表达式可以避免字段名的硬编码,提高代码的可读性和安全性

java 复制代码
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper
    .like(StringUtils.isNotBlank(username), User::getName, username)
    .ge(ageBegin != null, User::getAge, ageBegin)
    .le(ageEnd != null, User::getAge, ageEnd);

@TableName 注解

@TableName 注解用于指定实体类对应的数据库表名。如下:

java 复制代码
@Data
@TableName("product")
public class Product {
    private Long id;
    private String name;
    private Integer price;
    @Version
    private Integer version;
}

如果没有使用 @TableName 注解,MyBatis-Plus 会默认使用类名小写形式作为表名

Condition 条件判断

MyBatis-Plus 的条件构造器支持条件判断,可以根据参数是否为 null 来决定是否添加该条件

java 复制代码
@Test
public void test08() {
    String username = null;
    Integer ageBegin = 10;
    Integer ageEnd = 24;
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    
    if(StringUtils.isNotBlank(username)){
        queryWrapper.like("username","a");
    }
    if(ageBegin != null){
        queryWrapper.ge("age", ageBegin);
    }
    if(ageEnd != null){
        queryWrapper.le("age", ageEnd);
    }
    
    List<User> users = userMapper.selectList(queryWrapper);
}

更简洁的写法是使用 Lambda 表达式:

java 复制代码
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper
    .like(StringUtils.isNotBlank(username), User::getName, username)
    .ge(ageBegin != null, User::getAge, ageBegin)
    .le(ageEnd != null, User::getAge, ageEnd);

乐观锁实现

乐观锁是解决并发问题的一种有效方式。MyBatis-Plus 通过 @Version 注解实现乐观锁功能

配置乐观锁插件

在 config 包下配置乐观锁插件:

java 复制代码
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}

实体类添加版本号字段

在实体类中添加版本号字段(@Version):

java 复制代码
@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;
    @Version
    private Integer version;
}

乐观锁测试

java 复制代码
@Test
public void testConcurrentVersionUpdate() {
    // 小李取数据
    Product p1 = productMapper.selectById(1L);
    
    // 小王取数据
    Product p2 = productMapper.selectById(1L);
    
    // 小李修改 + 50
    p1.setPrice(p1.getPrice() + 50);
    int result1 = productMapper.updateById(p1);
    
    // 小王修改 - 30
    p2.setPrice(p2.getPrice() - 30);
    int result2 = productMapper.updateById(p2);
    
    if (result2 == 0) {
        // 失败重试,重新获取version并更新
        p2 = productMapper.selectById(1L);
        p2.setPrice(p2.getPrice() - 30);
        result2 = productMapper.updateById(p2);
    }
}

代码生成器

MyBatis-Plus 提供了代码生成器,可以快速生成 Entity、Mapper、Service、Controller 等代码:

java 复制代码
FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/mybatis_plus?characterEncoding=utf-8&userSSL=false", "root", "123456")
        .globalConfig(builder -> {
            builder.author("qcby")
                    .fileOverride()
                    .outputDir("D://mybatis_plus");
        })
        .packageConfig(builder -> {
            builder.parent("com.qcby")
                    .moduleName("mybatisplus")
                    .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://mybatis_plus"));
        })
        .strategyConfig(builder -> {
            builder.addInclude("t_user")
                    .addTablePrefix("t_", "c_");
        })
        .templateEngine(new FreemarkerTemplateEngine())
        .execute();

多数据源配置

MyBatis-Plus 结合 dynamic-datasource 可以轻松实现多数据源配置

数据源配置

在 application.yml 中配置多个数据源

XML 复制代码
spring:
  datasource:
    dynamic:
      primary: master
      strict: false
      datasource:
        master:
          url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false
          driver-class-name: com.mysql.cj.jdbc.Driver
          type: com.zaxxer.hikari.HikariDataSource
          username: root
          password: 123456
        slave_1:
          url: jdbc:mysql://localhost:3306/mybatis_plus_1?characterEncoding=utf-8&useSSL=false
          driver-class-name: com.mysql.cj.jdbc.Driver
          type: com.zaxxer.hikari.HikariDataSource
          username: root
          password: 123456

服务层指定数据源

在服务实现类上使用 @DS 注解指定数据源

java 复制代码
@DS("master")
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

@DS("slave_1")
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {
}

多数据源测试

java 复制代码
@Test
public void testDynamicDataSource(){
    System.out.println(userService.getById(1L));  // 使用master数据源
    System.out.println(productService.getById(1L));  // 使用slave_1数据源
}
相关推荐
柊二三1 小时前
XML的简略知识点
xml·数据库·oracle
岁忧1 小时前
macOS配置 GO语言环境
开发语言·macos·golang
朝朝又沐沐2 小时前
算法竞赛阶段二-数据结构(36)数据结构双向链表模拟实现
开发语言·数据结构·c++·算法·链表
木棉软糖2 小时前
一个MySQL的数据表最多能够存多少的数据?
java
魔尔助理顾问3 小时前
系统整理Python的循环语句和常用方法
开发语言·后端·python
Ares-Wang3 小时前
JavaScript》》JS》 Var、Let、Const 大总结
开发语言·前端·javascript
程序视点3 小时前
Java BigDecimal详解:小数精确计算、使用方法与常见问题解决方案
java·后端
愿你天黑有灯下雨有伞3 小时前
Spring Boot SSE实战:SseEmitter实现多客户端事件广播与心跳保活
java·spring boot·spring
每天敲200行代码3 小时前
MySQL 事务管理
数据库·mysql·事务
巴里巴气3 小时前
MongoDB索引及其原理
数据库·mongodb