mybatisplus分页
@Test void testpage(){ IPage<User> page =new Page<>(1,3); userDao.selectPage(page,null); System.out.println("当前页码值:"+page.getCurrent()); System.out.println("每页显示数:"+page.getSize()); System.out.println("一共多少页:"+page.getPages()); System.out.println("一共多少条数据:"+page.getTotal()); System.out.println("数据:"+page.getRecords()); }
DQL编程控制
简化控制台日志输出
# mybatis-plus日志控制台输出 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: banner: off # 关闭mybatisplus启动图标 spring: main: banner-mode: off # 关闭SpringBoot启动图标(banner)
创建Wrapper对象
//1.使用Wrapper对象 QueryWrapper wq=new QueryWrapper(); wq.lt("age",30); List<User> users = userDao.selectList(wq); System.out.println(users); //2.使用lambda QueryWrapper<User> qw = new QueryWrapper<User>(); qw.lambda().lt(User::getAge, 10);//添加条件 List<User> userList = userDao.selectList(qw); System.out.println(userList); //3.使用LambdaQueryWrapper对象 LambdaQueryWrapper<User> wq=new LambdaQueryWrapper<>(); wq.lt(User::getAge,30);//支持链式 List<User> users = userDao.selectList(wq); System.out.println(users); }
null值处理
//3.null值处理 UserQuery uq=new UserQuery(); uq.setAge(30); //uq.setAge2(10); LambdaQueryWrapper<User> lqw=new LambdaQueryWrapper<>(); lqw.gt(null != uq.getAge2(),User::getAge,uq.getAge2()) .lt(uq.getAge()!= null,User::getAge,uq.getAge()); List<User> users = userDao.selectList(lqw); System.out.println(users);
查询指定字段(使用LambdaQueryWrapper的select方法)
LambdaQueryWrapper<User> lambdaQueryWrapper=new LambdaQueryWrapper<>(); lambdaQueryWrapper.select(User::getId,User::getName); List<User> users = userDao.selectList(lambdaQueryWrapper); System.out.println(users); //如果不用Lambda,则需要指定字段 QueryWrapper<User> lqw = new QueryWrapper<User>(); lqw.select("id","name","age","tel");
聚合查询
QueryWrapper<User> lqw=new QueryWrapper<>(); lqw.select("count(*) as count"); List<Map<String, Object>> maps = userDao.selectMaps(lqw); System.out.println(maps);
分组查询(使用QueryWrapper的groupby)方法
QueryWrapper<User> lqw=new QueryWrapper<>(); lqw.select("count(*) as count,tel"); lqw.groupBy("tel"); List<Map<String, Object>> maps = userDao.selectMaps(lqw); System.out.println(maps);
条件构造器
eq,like,likeleft,between....
排序查询
orderBy
LambdaQueryWrapper<User> lwq = new LambdaQueryWrapper<>(); /** * condition :条件,返回boolean, 当condition为true,进行排序,如果为false,则不排序 * isAsc:是否为升序,true为升序,false为降序 * columns:需要操作的列 */ lwq.orderBy(true,false, User::getId);
映射匹配问题
-
数据库表名与pojo类名不同
使用@TableName("数据库表名")同步
-
编码中添加了数据库中未定义的属性
使用@TableField(exist = false)
-
采用默认查询开放了更多的字段查看权限(限制敏感数据)
使用@TableField(select = false)
-
字段名与属性名不同
用@TableField(value="字段名")
DML编程控制
id生成策略控制(insert)
AUTO:在字段上注解@TableId(type = IdType.AUTO) NONE: 不设置id生成策略 INPUT:用户手工输入id ASSIGN_ID:雪花算法生成id(可兼容数值型与字符串型) ASSIGN_UUID:以UUID生成算法作为id生成策略 其他的几个策略均已过时,都将被ASSIGN_ID和ASSIGN_UUID代替掉
NONE: 不设置id生成策略,MP不自动生成,约等于INPUT,所以这两种方式都需要用户手动设置,但是手动设置第一个问题是容易出现相同的ID造成主键冲突,为了保证主键不冲突就需要做很多判定,实现起来比较复杂 AUTO:数据库ID自增,这种策略适合在数据库服务器只有1台的情况下使用,不可作为分布式ID使用 ASSIGN_UUID:可以在分布式的情况下使用,而且能够保证唯一,但是生成的主键是32位的字符串,长度过长占用空间而且还不能排序,查询性能也慢 ASSIGN_ID:可以在分布式的情况下使用,生成的是Long类型的数字,可以排序性能也高,但是生成的策略和服务器时间有关,如果修改了系统时间就有可能导致出现重复主键 综上所述,每一种主键策略都有自己的优缺点,根据自己项目业务的实际情况来选择使用才是最明 智的选择。
简化配置
mybatis-plus: global-config: db-config: id-type: assign_id mybatis-plus: global-config: db-config: table-prefix: tbl_
多记录操作(Delete,Select)
使用deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList)
逻辑删除(Delete/Update)
物理删除:业务数据从数据库中丢弃,执行的是delete操作
逻辑删除:为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库中,执行的是update操作
-
数据库表添加 deleted 列,设默认值为0
-
实体类添加属性,注解 @TableLogic(value:逻辑未删除值 delval:逻辑删除值)
-
运行删除方法
-
发现后台执行的update操作
乐观锁(Update)
乐观锁的实现方式: 数据库表中添加version列,比如默认值给1 第一个线程要修改数据之前,取出记录时,获取当前数据库中的version=1 第二个线程要修改数据之前,取出记录时,获取当前数据库中的version=1 第一个线程执行更新时,set version = newVersion where version = oldVersion newVersion = version+1 [2] oldVersion = version [1] 第二个线程执行更新时,set version = newVersion where version = oldVersion newVersion = version+1 [2] oldVersion = version [1] 假如这两个线程都来更新数据,第一个和第二个线程都可能先执行 假如第一个线程先执行更新,会把version改为2, 第二个线程再更新的时候,set version = 2 where version = 1,此时数据库表的数据version已经为2,所以第二个线程会修改失败 假如第二个线程先执行更新,会把version改为2,第一个线程再更新的时候,set version = 2 where version = 1,此时数据库表的数 据version已经为2,所以第一个线程会修改失败不管谁先执行都会确保只能有一个线程更新数据,这就是MP提供的乐观锁的实现原理分析。
具体实现
-
数据库添加列名:使用version ,默认值为1
-
pojo类添加对应的字段名,并且打上@Version注解
-
添加乐观锁的拦截器new OptimisticLockerInnerInterceptor()
-
执行update操作
代码生成器