SpringBoot入门教程06——整合mybatis-plus(二)
SpringBoot入门教程06——整合mybatis-plus(二)
大纲
- springboot整合mybatis-plus入门,以及mybatis-plus代码生成工具入门,传送门
- 事务控制
- 分页
- 自定义SQL
- 条件构造器Wrapper入门
事务控制
- 在springboot启动类上加@EnableTransactionManagement注解
- 在要做事务控制的类或者方法上加@Transactional注解
来个例子,在UserController中增加如下代码
@Transactional @RequestMapping("/addError") public Object addEoor(){ Random random = new Random(); User user = new User(); user.setName("zzz"+random.nextInt(100)); user.setAge(random.nextInt(100)); userMapper.insert(user); int k=2/0; user = new User(); user.setName("kkk"+random.nextInt(100)); user.setAge(random.nextInt(100)); userMapper.insert(user); return user; }
重启应用,打开浏览器打开浏览器输入http://127.0.0.1:8080/user/addError,会发现2条数据都没有插入数据库,而如果把@Transactional注释掉,再刷新浏览器,会发现第一条数据成功插入到数据库中
补充一点,启动类不加@EnableTransactionManagement注解,只有@Transactional注解事务也会生效
分页
分页的实现非常简单,只需要在应用启动时,向spring容器注入分页拦截器PaginationInterceptor的实例即可
代码如下:
@Configuration public class MybatisPlusConfig { @Bean public PaginationInterceptor paginationInterceptor() { PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false // paginationInterceptor.setOverflow(false); // 设置最大单页限制数量,默认 500 条,-1 不受限制 // paginationInterceptor.setLimit(500); // 开启 count 的 join 优化,只针对部分 left join paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true)); return paginationInterceptor; } }
然后在查询的时候传入Page对象即可实现分页查询,UserController加入如下代码
@RequestMapping("/page") public Object page(@RequestParam(value = "pageNum",defaultValue = "1") Integer pageNum,@RequestParam(defaultValue = "2") Integer pageSize){ QueryWrapper<User> wrapper = new QueryWrapper<>(); Page<User> page = new Page(pageNum,pageSize); Page<User> userPage = userMapper.selectPage(page, wrapper); return userPage; }
自定义SQL
尽管mybatis-plus给我们提供了强大的条件构造器Wrapper,支持常见的CRUD操作,但是实际开发中仍避免不了要手动写sql。比如现在要查user表id为偶数的数据,实现方式有以下几种
- @Select注解实现
- xml文件实现
- 基于@Select注解或者xml文件,使用Wrapper辅助实现
直接上代码,先来UserMapper
List<User> selectListByEvenId(); @Select("select * from user where id%2=1") List<User> selectListByOddId(); @Select("select * from user ${ew.customSqlSegment}") List<User> selectAll(@Param(Constants.WRAPPER) Wrapper wrapper);
UserMapper.xml
<select id="selectListByEvenId" resultType="com.henry.entity.User"> SELECT * FROM user where id%2=0 </select>
UserController
@RequestMapping("/even") public Object even(){ List<User> userList = userMapper.selectListByEvenId(); return userList; } @RequestMapping("/odd") public Object odd(){ List<User> userList = userMapper.selectListByOddId(); return userList; } @RequestMapping("/selectAll") public Object selectAll(){ List<User> userList = userMapper.selectAll(new QueryWrapper()); return userList; }
代码一看就能明白,这里说一下几个可能遇到的坑
- 使用Wrapper辅助实现sql时,如果传的Wrapper实例是null,会报空指针错误,可以按照selectAll方法中的写法规避
- 如果mapper.xml和mapper接口都放在com.xxx.mapper包下,调用even()方法时会报sql没绑定的错误,此时需要修改一下pom文件,支持编译xml文件
pom文件修改如下
<build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> <include>**/*.json</include> </includes> </resource> </resources> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
条件构造器Wrapper
条件构造器Wrapper是mybatis-plus抽象出来用来生成sql语句片段的接口,Wrapper接口支持在不写sql语句的情况下,自动生成sql语句对数据库表进行增删改查,包括一些比较复杂的条件查询。
我们先看一下Wrapper接口的类图
顶层接口Wrapper,然后有2个抽象类AbstractWrapper和AbstractChainWrapper继承Wrapper接口,其中AbstractChainWrapper算是AbstractWrapper使用装饰着模式创建出来的一个类,其wrapperChildren属性是通过构造函数传入的AbstractWrapper实现类的实例。
了解装饰者设计模式的同学应该知道
- 装饰者模式的主要作用是给一个类添加新功能
- 主要实现方式:装饰类和被装饰类实现相同接口,然后装饰类通过构造函数传入被装饰类,装饰类的接口实现全部通过被装饰类实例方法实现,可以在方法中做增强
所以我们先看AbstractWrapper类,AbstractWrapper类中方法很多,基本上见名知义
allEq
allEq(Map<R, V> params) allEq(Map<R, V> params, boolean null2IsNull) allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
参数说明:
params:
key为数据库字段名,
value为字段值
null2IsNull: 为
true则在
map的
value为
null时调用 isNull 方法,为
false时则忽略
value为
null的
condition:为
true时才生成sql片段
- 例1:
allEq({id:1,name:"老王",age:null})
—>id = 1 and name = '老王' and age is null
- 例2:
allEq({id:1,name:"老王",age:null}, false)
—>id = 1 and name = '老王'
eq
eq(R column, Object val) eq(boolean condition, R column, Object val)
- 等于 =
- 例:
eq("name", "老王")
—>name = '老王'
ne
ne(R column, Object val) ne(boolean condition, R column, Object val)
- 不等于 <>
- 例:
ne("name", "老王")
—>name <> '老王'
gt
gt(R column, Object val) gt(boolean condition, R column, Object val)
- 大于 >
- 例:
gt("age", 18)
—>age > 18
ge
ge(R column, Object val) ge(boolean condition, R column, Object val)
- 大于等于 >=
- 例:
ge("age", 18)
—>age >= 18
lt
lt(R column, Object val) lt(boolean condition, R column, Object val)
- 小于 <
- 例:
lt("age", 18)
—>age < 18
le
le(R column, Object val) le(boolean condition, R column, Object val)
- 小于等于 <=
- 例:
le("age", 18)
—>age <= 18
between
between(R column, Object val1, Object val2) between(boolean condition, R column, Object val1, Object val2)
- BETWEEN 值1 AND 值2
- 例:
between("age", 18, 30)
—>age between 18 and 30
notBetween
notBetween(R column, Object val1, Object val2) notBetween(boolean condition, R column, Object val1, Object val2)
- NOT BETWEEN 值1 AND 值2
- 例:
notBetween("age", 18, 30)
—>age not between 18 and 30
like
like(R column, Object val) like(boolean condition, R column, Object val)
- LIKE ‘%值%’
- 例:
like("name", "王")
—>name like '%王%'
notLike
notLike(R column, Object val) notLike(boolean condition, R column, Object val)
- NOT LIKE ‘%值%’
- 例:
notLike("name", "王")
—>name not like '%王%'
likeLeft
likeLeft(R column, Object val) likeLeft(boolean condition, R column, Object val)
- LIKE ‘%值’
- 例:
likeLeft("name", "王")
—>name like '%王'
likeRight
likeRight(R column, Object val) likeRight(boolean condition, R column, Object val)
- LIKE ‘值%’
- 例:
likeRight("name", "王")
—>name like '王%'
isNull
isNull(R column) isNull(boolean condition, R column)
- 字段 IS NULL
- 例:
isNull("name")
—>name is null
isNotNull
isNotNull(R column) isNotNull(boolean condition, R column)
- 字段 IS NOT NULL
- 例:
isNotNull("name")
—>name is not null
in
in(R column, Collection<?> value) in(boolean condition, R column, Collection<?> value)
- 字段 IN (value.get(0), value.get(1), …)
- 例:
in("age",{1,2,3})
—>age in (1,2,3)
in(R column, Object... values) in(boolean condition, R column, Object... values)
- 字段 IN (v0, v1, …)
- 例:
in("age", 1, 2, 3)
—>age in (1,2,3)
notIn
notIn(R column, Collection<?> value) notIn(boolean condition, R column, Collection<?> value)
- 字段 NOT IN (value.get(0), value.get(1), …)
- 例:
notIn("age",{1,2,3})
—>age not in (1,2,3)
notIn(R column, Object... values) notIn(boolean condition, R column, Object... values)
- 字段 NOT IN (v0, v1, …)
- 例:
notIn("age", 1, 2, 3)
—>age not in (1,2,3)
inSql
inSql(R column, String inValue) inSql(boolean condition, R column, String inValue)
- 字段 IN ( sql语句 )
- 例:
inSql("age", "1,2,3,4,5,6")
—>age in (1,2,3,4,5,6)
- 例:
inSql("id", "select id from table where id < 3")
—>id in (select id from table where id < 3)
notInSql
notInSql(R column, String inValue) notInSql(boolean condition, R column, String inValue)
- 字段 NOT IN ( sql语句 )
- 例:
notInSql("age", "1,2,3,4,5,6")
—>age not in (1,2,3,4,5,6)
- 例:
notInSql("id", "select id from table where id < 3")
—>id not in (select id from table where id < 3)
groupBy
groupBy(R... columns) groupBy(boolean condition, R... columns)
- 分组:GROUP BY 字段, …
- 例:
groupBy("id", "name")
—>group by id,name
orderByAsc
orderByAsc(R... columns) orderByAsc(boolean condition, R... columns)
- 排序:ORDER BY 字段, … ASC
- 例:
orderByAsc("id", "name")
—>order by id ASC,name ASC
orderByDesc
orderByDesc(R... columns) orderByDesc(boolean condition, R... columns)
- 排序:ORDER BY 字段, … DESC
- 例:
orderByDesc("id", "name")
—>order by id DESC,name DESC
orderBy
orderBy(boolean condition, boolean isAsc, R... columns)
- 排序:ORDER BY 字段, …
- 例:
orderBy(true, true, "id", "name")
—>order by id ASC,name ASC
having
having(String sqlHaving, Object... params) having(boolean condition, String sqlHaving, Object... params)
- HAVING ( sql语句 )
- 例:
having("sum(age) > 10")
—>having sum(age) > 10
- 例:
having("sum(age) > {0}", 11)
—>having sum(age) > 11
or
or() or(boolean condition)
- 拼接 OR
注意事项:
主动调用
or表示紧接着下一个方法不是用
and连接!(不调用
or则默认为使用
and连接)
- 例:
eq("id",1).or().eq("name","老王")
—>id = 1 or name = '老王'
or(Consumer<Param> consumer) or(boolean condition, Consumer<Param> consumer)
- OR 嵌套
- 例:
or(i -> i.eq("name", "李白").ne("status", "活着"))
—>or (name = '李白' and status <> '活着')
and
and(Consumer<Param> consumer) and(boolean condition, Consumer<Param> consumer)
- AND 嵌套
- 例:
and(i -> i.eq("name", "李白").ne("status", "活着"))
—>and (name = '李白' and status <> '活着')
nested
nested(Consumer<Param> consumer) nested(boolean condition, Consumer<Param> consumer)
- 正常嵌套 不带 AND 或者 OR
- 例:
nested(i -> i.eq("name", "李白").ne("status", "活着"))
—>(name = '李白' and status <> '活着')
apply
apply(String applySql, Object... params) apply(boolean condition, String applySql, Object... params)
- 拼接 sql
注意事项:
该方法可用于数据库函数 动态入参的
params对应前面
applySql内部的
{index}部分.这样是不会有sql注入风险的,反之会有!
- 例:
apply("id = 1")
—>id = 1
- 例:
apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
—>date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
- 例:
apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")
—>date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
last
last(String lastSql) last(boolean condition, String lastSql)
- 无视优化规则直接拼接到 sql 的最后
注意事项:
只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用
- 例:
last("limit 1")
exists
exists(String existsSql) exists(boolean condition, String existsSql)
- 拼接 EXISTS ( sql语句 )
- 例:
exists("select id from table where age = 1")
—>exists (select id from table where age = 1)
notExists
notExists(String notExistsSql) notExists(boolean condition, String notExistsSql)
- 拼接 NOT EXISTS ( sql语句 )
- 例:
notExists("select id from table where age = 1")
—>not exists (select id from table where age = 1)
- SpringBoot从入门到精通教程(三十二)- MybatisPlus框架动态数据源用法(支持多个DB,动态切换数据源)
- SpringBoot从入门到精通教程(二十五)- Mybatis-Plus快速开发框架用法
- SpringBoot整合MyBatis-Plus3.1教程详解
- SpringBoot从入门到精通教程(十二)- Dubbo服务提供者、服务消费者整合/Zookeeper集成(最终篇)
- spring整合mybatis(入门级简单教程1)--在spring中配置c3p0,并成功测试
- SpringBoot非官方教程 | 第六篇:springboot整合mybatis
- SpringBoot 入门教程:集成mybatis,redis
- spring整合mybatis(入门级简单教程2)
- 企业级 SpringBoot 教程 (六)springboot整合mybatis
- SpringBoot入门学习以及整合MyBatis
- spring整合mybatis(入门级简单教程3)--获取sqlSession对象
- Spring Boot整合mybatis全注解入门教程
- spring整合mybatis(入门级简单教程4)--扫描mapper类
- springBoot入门总结(五)整合Mybatis(注解方式)
- spring整合mybatis(入门级简单教程5)--使用mybatis的API
- [置顶] SSM框架——详细整合教程(Spring+SpringMVC+MyBatisPlus+Maven)
- SpringBoot从入门到精通教程(六)- Mysql和Mybatis+XML用法详解
- SSM(Spring+SpringMVC+MyBatis)框架快速整合入门教程
- SpringBoot整合mybatis-plus入门
- springboot2.3整合mybatis-plus3.3.2较为详细的教程