MybatisPlus学习总结(下)
Posted AC_Jobim
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MybatisPlus学习总结(下)相关的知识,希望对你有一定的参考价值。
MybatisPlus学习总结(下)
一、条件构造器
在MP中,Wrapper接口的实现类关系如下:
## mybatis plus基本操作
查询方式 说明
setSqlSelect 设置 SELECT 查询字段
where WHERE 语句,拼接 + WHERE 条件
and AND 语句,拼接 + AND 字段=值
andNew AND 语句,拼接 + AND (字段=值)
or OR 语句,拼接 + OR 字段=值
orNew OR 语句,拼接 + OR (字段=值)
eq 等于=
allEq 基于 map 内容等于=
ne 不等于<>
gt 大于>
ge 大于等于>=
lt 小于<
le 小于等于<=
like 模糊查询 LIKE
notLike 模糊查询 NOT LIKE
in IN 查询
notIn NOT IN 查询
isNull NULL 值查询
isNotNull IS NOT NULL
groupBy 分组 GROUP BY
having HAVING 关键词
orderBy 排序 ORDER BY
orderAsc ASC 排序 ORDER BY
orderDesc DESC 排序 ORDER BY
exists EXISTS 条件语句
notExists NOT EXISTS 条件语句
between BETWEEN 条件语句
notBetween NOT BETWEEN 条件语句
addFilter 自由拼接 SQL
last 拼接在最后,例如:last("LIMIT 1")
注意! xxNew 都是另起 ( ... ) 括号包裹。
1.1 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 的
- 例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 = '老王’
allEq(BiPredicate<R, V> filter, Map<R, V> params)
allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean
null2IsNull)
个别参数说明: filter : 过滤函数,是否允许字段传入比对条件中 ,params 与 null2IsNull : 同上
- 例1: allEq((k,v) -> k.indexOf(“a”) > 0, {id:1,name:“老王”,age:null}) —> name = ‘老王’
and age is null- 例2: allEq((k,v) -> k.indexOf(“a”) > 0, {id:1,name:“老王”,age:null}, false) —> name =
'老王’
代码示例:
@Test
public void testAllEq(){
Map<String,Object> params = new HashMap<>();
params.put("name", "李四");
params.put("age", "20");
params.put("password", null);
QueryWrapper<User> wrapper = new QueryWrapper<>();
//SELECT id,user_name,name,age,email FROM tb_user WHERE (password IS NULL AND name = ? AND age = ?)
// wrapper.allEq(params);
//SELECT id,user_name,name,age,email FROM tb_user WHERE (name = ? AND age = ?)
// wrapper.allEq(params,false);
//过滤函数表示是否允许字段传入比对条件中 params
//SELECT id,user_name,name,age,email FROM tb_user WHERE (password IS NULL AND age = ?)
wrapper.allEq((k, v) -> (k.equals("age") || k.equals("id") || k.equals("password")) , params);
List<User> users = userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
1.2 基本比较操作
@Test
public void testEq() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
//SELECT id,user_name,name,age,email FROM tb_user WHERE (password = ? AND age >= ? AND name IN (?,?,?))
wrapper.eq("password", "123456")
.ge("age", 20)
.in("name", "李四", "王五", "赵六");
List<User> users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
结果:
1.3 模糊查询
代码示例:
@Test
public void testLike(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
//SELECT id,user_name,name,age,email FROM tb_user WHERE (name LIKE ?)
// 参数:%五(String)
wrapper.likeLeft("name", "五");
List<User> users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
结果:
1.4 排序
代码示例:
@Test
public void testOrderByAgeDesc(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
//按照年龄倒序排序
// SELECT id,user_name,name,age,email FROM tb_user ORDER BY age DESC
wrapper.orderByDesc("age");
List<User> users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
结果:
1.5 逻辑查询
代码示例:
@Test
public void testOr(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
// SELECT id,user_name,name,age,email FROM tb_user WHERE (name = ? OR age = ?)
wrapper.eq("name", "王五").or().eq("age", 21);
List<User> users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
结果:
1.6 select
在MP查询中,默认查询所有的字段,如果有需要也可以通过select方法进行指定字段。
代码示例:
@Test
public void testSelect(){
QueryWrapper<User> wrapper = new QueryWrapper<>();
//SELECT id,name,age FROM tb_user WHERE (name = ? OR age = ?)
wrapper.eq("name", "王五")
.or()
.eq("age", 21)
.select("id","name","age"); //指定查询的字段
List<User> users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
结果:
二、ActiveRecord
在Mybatis-Plus中提供了ActiveRecord
的模式,支持 ActiveRecord 形式调用,实体类只需继承 Model
类即可实现基本 CRUD 操作,简单来说就是一个实体类继承Model类,并通过注解与数据库的表名进行关联,这样就可以通过实体类直接进行表的简单增删改查操作
实现步骤:
-
Mapper对象要先继承BaseMapper对象
public interface UserMapper extends BaseMapper<User> { }
-
实体对象要继承Model对象
@Data @TableName("tb_user") public class User extends Model<User> { @TableId(value = "id",type = IdType.AUTO) private Long id; private String userName; @TableField(select = false)//查询的时候不查询该字段 private String password; private String name; private Integer age; private String email; @TableField(exist = false) private String address; //在数据库表中是不存在的 }
-
代码测试
@Test public void testSelectById(){ User user = new User(); user.setId(16L); //SELECT id,user_name,name,age,email FROM tb_user WHERE id=? User user1 = user.selectById(); System.out.println(user1); } @Test public void testInsert(){ User user = new User(); user.setUserName("diaochan"); user.setPassword("123456"); user.setAge(20); user.setName("貂蝉"); user.setEmail("diaochan@itcast.cn"); //INSERT INTO tb_user ( user_name, password, name, age, email ) VALUES ( ?, ?, ?, ?, ? ) // 调用AR的insert方法进行插入数据 boolean insert = user.insert(); System.out.println("result => " + insert); }
三、插件
3.1 mybatis的插件机制
参考博客:https://blog.csdn.net/oneby1314/article/details/116289510
3.2 常用插件配置
1、 防止全表更新与删除插件
- 针对 update 和 delete 语句 作用: 阻止恶意的全表更新删除
- SpringBoot配置:
如果进行全表的更新和删除操作则会抛出:@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 防止全表更新与删除 // 针对 update 和 delete 语句 interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); return interceptor; }
MybatisPlusException: Prohibition of table update operation
2、分页插件
-
插件配置:(SpringBoot)
@Configuration public class MybatisPlusConfig { // 配置分页插件,最新版 @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2)); return interceptor; } }
-
测试:
// 测试分页查询,前提:配置分页插件 @Test public void testSelectPage(){ Page<User> page = new Page<>(3,2); //查询 QueryWrapper<User> wrapper = new QueryWrapper<>(); //设置查询条件 // wrapper.like("email", "itcast");//like表示模糊查询 IPage<User> iPage = userMapper.selectPage(page, wrapper); System.out.println("数据总条数: " + iPage.getTotal()); System.out.println("数据总页数: " + iPage.getPages()); System.out.println("当前页数: " + iPage.getCurrent()); List<User> records = iPage.getRecords(); for (User record : records) { System.out.println(record); } }
执行结果:
3、乐观锁插件
-
插件配置:(SpringBoot)
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 添加乐观锁插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; }
-
为表添加version字段,并且设置初始值为1
ALTER TABLE `tb_user` ADD COLUMN `version` int(10) NULL AFTER `email`; UPDATE `tb_user` SET `version`='1';
-
为User实体对象添加version字段,并且添加@Version注解
@Version private Integer version;
-
测试
@Test public void testUpdateVersion(){ User user = new User(); user.setId(2L);// 查询条件 User userVersion = user.selectById(); user.setAge(23); // 更新的数据 user.setVersion(userVersion.getVersion()); // 当前的版本信息 boolean result = user.updateById(); System.out.println("result => " + result); }
执行结果:
-
注意:
支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
整数类型下 newVersion = oldVersion + 1
newVersion 会回写到 entity 中
四、MybatisPlus 扩展
4.1 Sql注入器
SQL注入器主要用于扩充BaseMapper中的方法。以扩展findAll方法为例。
-
编写MyBaseMapper
public interface MyBaseMapper<T> extends BaseMapper<T> { List<T> findAll(); }
其他的Mapper都可以继承该Mapper,这样实现了统一的扩展
public interface UserMapper extends MyBaseMapper<User> { }
-
编写MySqlInjector
如果直接继承
AbstractSqlInjector
的话,原有的BaseMapper中的方法将失效,所以我们选择继承DefaultSqlInjector
进行扩展。public class mysqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList(Class<?> mapperClass) { List<AbstractMethod> methodList = super.getMethodList(mapperClass); // 再扩充自定义的方法 methodList.add(new FindAll()); return methodList; } }
-
编写FindAll
public class FindAll extends AbstractMethod { @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { String sqlMethod = "findAll"; String sql = "select * from " + tableInfo.getTableName(); SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass); return this.对狂神说的MybatisPlus的学习总结
MybatisPlus实现基本CURD&逻辑删除&代码生成(对标Django系列学习二)