依赖
使用SpringBoot时在Maven添加Starter:
1 2 3 4 5 6 7 8 9 10 11 12 13
| <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.2</version> </dependency>
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.5.3</version> </dependency>
|
配置
与在SpringBoot中使用Mybatis一样,在application配置文件中配置数据源即可。
1 2 3 4 5 6 7 8 9 10 11 12
| spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 114514 url: jdbc:mysql://localhost:3306/tutorial
mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
Mapper
声明Mapper接口并继承MyBatisPlus中的BaseMapper<Entity>
:
1
| public interface MyMapper extends BaseMapper<My>{...}
|
这里My为这个Mapper主要操作的实体类。
然后在你@SpringBootApplication注解的启动类加上@MapperScan(“mapper包根目录”)
脱裤子放屁,只需要在Mapper接口上写上@Mapper注解就行了。
BaseMapper提供许多简单的、便利的操作功能。
Service
MybatisPlus的偷懒魔爪伸到了业务层,但实际上和Mapper的操作差不多。
1
| public class MyServiceImpl extends ServiceImpl<MyMapper,My> implements MyServiceIntf{...}
|
实体
实体和往常一样创建一个POJO类就行,但MybatisPlus提供了一些注解。
不要使用基本类型!
对实体类,默认是类名与表名完全对应(驼峰与下划线自动转换),当不对应是需要指定实体对应表名。
1 2
| @TableName("normal_table") public class MySuperObject{...}
|
与上述类似,当主键名称不对应可以指示(第一个参数value)。
第二个参数Type设置这个主键的生成策略,常用的有以下:
策略 |
效果 |
IdType.NONE |
默认,如果主键为空也不管,和往常一样引发异常 |
IdType.AUTO |
当数据库设置了主键自增,那么会自己填写自增后的ID;如果数据库中没有设置,同NONE |
IdType.ASSIGN_ID |
不管数据库有没有设置自增,如果为空都根据雪花算法生成一个ID |
1 2 3 4
| @TableId("normal_id",IdType.ASSIGN_ID) private Long superId;
|
与TableID基本一致,就是不用于主键。
启用逻辑删除。
在实体类某个属性(数据库表中也要有)添加,启用逻辑删除,此时Mybatis的各种操作只是将行数据(的那个属性)设置为已删除而不物理上地删除。
1 2
| @TableLogic private Integer isDeleted;
|
另外可以指定什么值代表已删除。
@TableLogic("未删除值","已删除值")
条件构造器
备忘录解释那么多干什么,看官网文档!
其实就是类似于某些ORM框架,把SQL转化为有类型的、链式的方法调用,如query.like(My::Name, "江").gt(My::Age, 96)
。
条件构造器按如何区分字段可分为XxxWrapper和LambdaXxxWrapper(上面的例子就是),按可以进行的操作可以分为QueryWrapper和UpdateWrapper。尽量使用LambdaXxxWrapper。
如果Mapper是继承了BaseMapper的话,他都会有使用条件构造器的方法,简单使用如下:
1 2 3 4 5 6 7
| ... QueryWrapper<My> wp = new QueryWrapper<>(); wp.like(My::getName, "江") .gt(My::getAge, 96) .orderByAsc(My::getAge); myMapper.selectList(wp); ...
|
使用QueryWrapper也可以修改:
1 2 3 4 5 6 7 8 9 10
| My newMy = new My(); ...
QueryWrapper<My> wp = new QueryWrapper<>(); wp.like(My::getName, "江") .gt(My::getAge, 96) .orderByAsc(My::getAge);
myMapper.update(newMy, wp);
|
但修改的正统方法是通过UpdateWrapper:
1 2 3 4 5 6 7 8
| UpdateWrapper<My> wp = new UpdateWrapper<>(); wp.like(My::getName, "江") .gt(My::getAge, 96) .orderByAsc(My::getAge) .set(My::getAge, 95) .set() ... myMapper.update(null, wp);
|
子查询可以通过.inSql()
或.notInSql()
方法判断是否在子查询集合。
需要根据条件开关Wrapper某个小条件,注意到condition参数。
自带的分页插件
MybatisPlus的插件的添加方法都是通过配置类(本文是SpringBoot!):
1 2 3 4 5 6 7 8 9 10
| @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.你的数据库类型)); return interceptor; } }
|
使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Page<My> toPage = new Page<>(从1起的页数不是INDEX, 每页多少条);
QueryWrapper<My> wrapper = new QueryWrapper<>(); wrapper.like(My::getName, "江");
IPage<My> iPage = myMapper.selectPage(toPage, wrapper);
System.out.println("当前页:" + iPage.getCurrent()); System.out.println("总页数:" + iPage.getPages()); System.out.println("每一页显示的条数:" + iPage.getSize()); System.out.println("总条数:" + iPage.getTotal());
return iPage.getRecords();
|
自定义查询中也可以使用这个分页插件,只需要第一个参数为Page,SQL中不需要写limit之类的。