您的位置:首页 > 编程语言 > Java开发

SpringBoot入门教程06——整合mybatis-plus(二)

2020-07-15 05:52 218 查看

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

代码一看就能明白,这里说一下几个可能遇到的坑

  1. 使用Wrapper辅助实现sql时,如果传的Wrapper实例是null,会报空指针错误,可以按照selectAll方法中的写法规避
  2. 如果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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: