MybatisPlus学习总结(下)

Posted AC_Jobim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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类,并通过注解与数据库的表名进行关联,这样就可以通过实体类直接进行表的简单增删改查操作

实现步骤:

  1. Mapper对象要先继承BaseMapper对象

    public interface UserMapper extends BaseMapper<User> {
    }
    
  2. 实体对象要继承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; //在数据库表中是不存在的
    }
    
  3. 代码测试

    @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、分页插件

  1. 插件配置:(SpringBoot)

    @Configuration
    public class MybatisPlusConfig {
        // 配置分页插件,最新版
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
            return interceptor;
        }
    
    }
    
  2. 测试:

    // 测试分页查询,前提:配置分页插件
    @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、乐观锁插件

  1. 插件配置:(SpringBoot)

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
    
  2. 为表添加version字段,并且设置初始值为1

    ALTER TABLE `tb_user`
    ADD COLUMN `version` int(10) NULL AFTER `email`;
    UPDATE `tb_user` SET `version`='1';
    
  3. 为User实体对象添加version字段,并且添加@Version注解

    @Version
    private Integer version;
    
  4. 测试

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

    执行结果:

  5. 注意:

    支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
    整数类型下 newVersion = oldVersion + 1
    newVersion 会回写到 entity 中

四、MybatisPlus 扩展

4.1 Sql注入器

SQL注入器主要用于扩充BaseMapper中的方法。以扩展findAll方法为例。

  1. 编写MyBaseMapper

    public interface MyBaseMapper<T> extends BaseMapper<T> {
        List<T> findAll();
    }
    
    

    其他的Mapper都可以继承该Mapper,这样实现了统一的扩展

    public interface UserMapper extends MyBaseMapper<User> {
    }
    
  2. 编写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;
        }
    }
    
  3. 编写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系列学习二)

    SpringBoot整合MybatisPlus有关条件构造器的相关查询方法

    MyBatisPlus

    Python学习总结

    MybatisPlus 学习代码生成器