什么是MybatisPlus

MybatisPlus可以节省大量时间,所有的CRUD代码都可以自动化完成
MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
官网:https://baomidou.com/

使用

配置

 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
server:  
  port: 8082  
  servlet:  
    context-path: /oc-app  
spring:  
  jackson:  
    time-zone: GMT+8  
  datasource:  
    dynamic:  
      primary: db1  
      datasource:  
        db1:  
          # 数据库的JDBC链接  
          url: jdbc:mysql://127.0.0.1:3306/test?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf8&useSSL=false&useLegacyDatetimeCode=false&&serverTimezone=Asia/Shanghai  
          # 数据库用户名  
          username: root  
          # 数据库密码  
          password: 123456  
        db2:  
          # 数据库的JDBC链接  
          url: jdbc:mysql://127.0.0.1:3306/admin?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf8&useSSL=false&useLegacyDatetimeCode=false&&serverTimezone=Asia/Shanghai  
          # 数据库用户名  
          username: root  
          # 数据库密码  
          password: 654321  
  flyway: # 是否启用flyway  
    enabled: true  
    # 编码格式,默认UTF-8  
    encoding: UTF-8  
    # 迁移sql脚本文件存放路径,默认db/migration  
    locations: classpath:db/migration  
    # 迁移sql脚本文件名称的前缀,默认V  
    sql-migration-prefix: V  
    # 迁移sql脚本文件名称的分隔符,默认2个下划线__  
    sql-migration-separator: __  
    # 迁移sql脚本文件名称的后缀  
    sql-migration-suffixes: .sql  
    # 迁移时是否进行校验,默认true  
    validate-on-migrate: true  
    # 当迁移发现数据库非空且存在没有元数据的表时,自动执行基准迁移,新建schema_version表  
    baseline-on-migrate: true  
  redis:  
    host: 192.168.1.1 
    port: 6379  
    password: admin@123!  
  cache:  
    type: REDIS  
    redis:  
      time-to-live: 120  
  mvc:  
    pathmatch:  
      matching-strategy: ant_path_matcher  
  
  main:  
    allow-bean-definition-overriding: true  
    # mybatis plus 配置  
mybatis-plus:  
  configuration: # 下划线转驼峰  
    map-underscore-to-camel-case: true  
    #日志打印  
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  
    # 扫描 xml 文件位置  
  mapper-locations: classpath:mapper/*Mapper.xml  
  global-config:  
    db-config: # 使用雪花算法主键填充策略  
      id-type: assign_id

在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:

1
2
3
4
5
6
7
@SpringBootApplication
@MapperScan("com.xx.mapper")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

实现

实体类

1
2
3
4
5
6
7
@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

编写 Mapper 包下的 UserMapper接口

1
2
3
public interface UserMapper extends BaseMapper<User> {

}

service层及实现类

1
2
3
4
5
6
7
public interface UserService extends IService<User> {  
}

@Service  
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {  
  
}

注解

@TableId(value = “user_id”, type = IdType.ASSIGN_ID)
private Long userId; 分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法) 如上使用的id为雪花算法生成的,比较长,建议使用自增AUTO,数据库不进行物理删除,而是逻辑删除

表达式与sql对比

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
eq == equal  等于
ne == not equal 不等于
gt == greater than 大于
lt == less than 小于
ge ==  greater than or equal 大于等于
le == less than or equal 小于等于
in == in 包含(数组)
isNull == 等于null
isNotNull == 不等于null
orderByDesc == 倒序排序
orderByAsc == 升序排序
or == 或者
and == 并且
between == 在2个条件之间(包括边界值)
like == 模糊查询
clear == 清除
apply == 拼接sql
lambda == 使用lambda表达式
exists == 临时表

常用注解

实体类中创建时间以及修改时间可以加入

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
/**  
 * 创建时间  
 */  
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")  
@TableField(fill = FieldFill.INSERT)  
private LocalDateTime createTime;  
  
/**  
 * 更新时间  
 */  
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")  
@TableField(fill = FieldFill.INSERT_UPDATE)  
private LocalDateTime updateTime;

编写处理器来处理这个注释就会在写操作时候自动生成当前时间

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
/**  
 * 实现自动化操作创建时间和修改时间  
 */  
@Component  
public class DateTimeFillConfig implements MetaObjectHandler {  
    @Override  
    public void insertFill(MetaObject metaObject) {  
        //设置属性值  
        this.setFieldValByName("createdTime", LocalDateTime.now(),metaObject);  
        this.setFieldValByName("updatedTime",LocalDateTime.now(),metaObject);  
    }  
  
    @Override  
    public void updateFill(MetaObject metaObject) {  
        this.setFieldValByName("updatedTime",LocalDateTime.now(),metaObject);  
    }  
}

复杂查询案例

 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
30
31
32
33
34
35
36
        //封装查询条件
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
		//模糊查询
		queryWrapper.like("a.nick_name", vo.getName());
		// 手机号/用户名称查询,当用户名为一串数字时默认使用手机号查询
        if (StringUtils.isNotBlank(vo.getNameOrMobile())) {
            if (NumberUtils.isDigits(vo.getNameOrMobile())) {
                queryWrapper.and(wq->wq.like("b.mobile", vo.getNameOrMobile())
                        .or().like("b.nick_name",vo.getNameOrMobile()));
            } else {
                queryWrapper.like("b.nick_name", vo.getNameOrMobile());
            }
        }
		// 时间范围查询
        if (StringUtils.isNotBlank(vo.getStartTime())) {
            queryWrapper.ge("a.created_time", vo.getStartTime());
        }
        if (StringUtils.isNotBlank(vo.getEndTime())) {
            queryWrapper.le("a.created_time", vo.getEndTime());
        } 
		// 精准查询
        if (StringUtils.isNotBlank(vo.getId())) {
            queryWrapper.eq("a.id", vo.getId());
        }
		//状态不在其中的
        if (StringUtils.isBlank(vo.getStatus()) && "2".equals(vo.getType())) {
            queryWrapper.notIn("a.status", List.of(1, 2, 3));
        }
		queryWrapper.notIn("a.status", List.of(1,2,3));
		// 时间进行排序
        // where语句后面不能直接增加排序,导致sql解析异常
        if (!queryWrapper.isEmptyOfWhere()) {
            queryWrapper.orderByDesc("a.created_time");
        }
		
		IPage<User> pages = getBaseMapper().getPageList(pager, queryWrapper);