自定义sql
除了Mybatis-plus自带的方法可以使用条件构造器,我们自定义sql也可以使用条件构造器。
将Wrapper作为Mapper接口方法参数并在该参数前加上@Param(Constants.WRAPPER),在sql中加入${ew.customSqlSegment},Mybatis-plus会自动帮我们解析
public interface UserMapper extends BaseMapper { // 查询年龄小于100的数据 @Select("select * from sys_user ${ew.customSqlSegment}") List selectAll(@Param(Constants.WRAPPER)Wrapper userWrapper);}
测试
@Testpublic void select10() { // 查询年龄小于100的数据 List users = userMapper.selectAll(Wrappers.lambdaQuery().lt(User::getAge,100)); log.info("年龄小于100的数据:{}",users);}
![f467e04ea3dad4cc3c8890895e9afdd5.png](https://img-blog.csdnimg.cn/img_convert/f467e04ea3dad4cc3c8890895e9afdd5.png)
如上示例所示,查询年龄小于100的数据自动在where语句后面拼接age。
分页
- 定义分页配置
@Configurationpublic class MybatisConfig { @Bean public PaginationInterceptor skymtPaginationInterceptor(SkyMybatisProperties properties) { // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false // paginationInterceptor.setOverflow(false); // 设置最大单页限制数量,默认 500 条,-1 不受限制 // paginationInterceptor.setLimit(500); // 开启 count 的 join 优化,只针对部分 left join // Mybatis-plus分页插件 PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); return paginationInterceptor; }}
- 测试
@Testpublic void select11() { // 分页查询,当前页数为1,每页长度为2 IPage users = userMapper.selectPage(new Page(1,2), Wrappers.lambdaQuery()); log.info("获取总数:{}",users.getTotal()); users.getRecords().forEach(user -> { log.info("用户数:{}", user); });}
![9a1c80dea7e65ac8c0e65ae210aa931d.png](https://img-blog.csdnimg.cn/img_convert/9a1c80dea7e65ac8c0e65ae210aa931d.png)
从结果可以看出,sql后面自动拼接了LIMIT,结果查询出两条数据,数据总个数为3,
需要注意的是分页插件默认最大页数为500,如果单页大于500最终查询出来的结果数也是500,所以当单页数大于500可以通过paginationInterceptor.setLimit();设置每页数
自定义分页
- 在UserMapper.java中添加分页方法
public interface UserMapper extends BaseMapper { //自定义分页查询,方式一(Mybatis-plus) @Select("select * from sys_user ${ew.customSqlSegment}") IPage selectUserPage(Page page, @Param(Constants.WRAPPER)Wrapper wrapper); //自定义分页查询,方式二(原生) @Select("select * from sys_user where age < #{age}") IPage selectUserPage2(Page page, @Param("age") Integer age);}
- 测试
@SpringBootTest@RunWith(SpringRunner.class)public class PageTest { @Autowired private UserMapper userMapper; // 自定义分页查询,方式一 @Test public void selectMyPage(){ // 分页查询,当前页数为1,每页长度为2, 查询年龄小于100 IPage users = userMapper.selectUserPage(new Page<>(1, 2), Wrappers.query().lambda().lt(User::getAge, 100)); log.info("获取总数:{}",users.getTotal()); users.getRecords().forEach(user -> { log.info("用户数:{}", user); }); } // 自定义分页查询,方式二 @Test public void selectMyPage2(){ // 分页查询,当前页数为1,每页长度为2, 查询年龄小于100 IPage users = userMapper.selectUserPage2(new Page<>(1, 2), 100); log.info("获取总数:{}",users.getTotal()); users.getRecords().forEach(user -> { log.info("用户数:{}", user); }); }}
更新方法
数据库有如下数据
![c910d8b32b12d4a9bba2b3287a74aa73.png](https://img-blog.csdnimg.cn/img_convert/c910d8b32b12d4a9bba2b3287a74aa73.png)
以条件构造器更新
前面我们已经讲过条件构造器,更新操作我们可以使用LambdaUpdateWrapper条件构造器
@Testpublic void update() { // 查询姓名为张三的数据 User beforeRepUser = userMapper.selectOne(Wrappers.lambdaQuery().eq(User::getName,"张三")); // 更新名字为“张三”&& 年龄为 32 年龄到33岁 LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper(); wrapper.eq(User::getName,"张三").eq(User::getAge,32); User user = new User(); user.setAge(33); userMapper.update(user, wrapper); // 查询姓名为张三的数据 User afterRepUser = userMapper.selectOne(Wrappers.lambdaQuery().eq(User::getName,"张三")); log.info("【更新前】姓名为张三的数据:{}",beforeRepUser); log.info("【更新后】姓名为张三的数据:{}",afterRepUser);}
![9557444a5a63f4a420242062ffa3314e.png](https://img-blog.csdnimg.cn/img_convert/9557444a5a63f4a420242062ffa3314e.png)
从结果看,姓名为“张三”并年龄为32的数据的年龄变成了33
条件构造器中的Set方法
在正常的开发中,有时我们可能只需要更新某个字段,此时再new对象赋值给Mapper方法显得有点麻烦,Mybatis-plus给我们提供了方便的处理方法,利用条件构造器中的Set方法
@Testpublic void update2() { // 查询姓名为张三的数据 User beforeRepUser = userMapper.selectOne(Wrappers.lambdaQuery().eq(User::getName,"张三")); // 更新名字为“张三”&& 年龄为 33 34 LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper(); wrapper.eq(User::getName,"张三").eq(User::getAge,33).set(User::getAge,34); userMapper.update(null, wrapper); // 查询姓名为张三的数据 User afterRepUser = userMapper.selectOne(Wrappers.lambdaQuery().eq(User::getName,"张三")); log.info("【更新前】姓名为张三的数据:{}",beforeRepUser); log.info("【更新后】姓名为张三的数据:{}",afterRepUser);}
![502662a9654f7ed2ae8001cf2a565155.png](https://img-blog.csdnimg.cn/img_convert/502662a9654f7ed2ae8001cf2a565155.png)
从结果看,姓名为“张三”并年龄为33的数据的年龄变成了34,所以当我们需要更新的字段非常少可以利用利用条件构造器中的Set方法更新。
空字符串或者null问题
在项目开发中,我们有时需要将列置为空字符串或null,但是当我们用Mybatis-plus原生方法调用时更新失败。
做如下测试:更新名字为“张三”的年龄为null,邮箱为zhangsannew@qq.com
@Testpublic void update3() { // 查询姓名为张三的数据 User beforeRepUser = userMapper.selectOne(Wrappers.lambdaQuery().eq(User::getName,"张三")); // 更新名字为“张三”的年龄为null,邮箱为zhangsannew@qq.com User user = new User(); user.setAge(null); user.setEmail("zhangsannew@qq.com"); userMapper.update(user, Wrappers.lambdaUpdate().eq(User::getName,"张三")); // 查询姓名为张三的数据 User afterRepUser = userMapper.selectOne(Wrappers.lambdaQuery().eq(User::getName,"张三")); log.info("【更新前】姓名为张三的数据:{}",beforeRepUser); log.info("【更新后】姓名为张三的数据:{}",afterRepUser);}
![2aefe35bf1fbd79ad3215239cf4c497a.png](https://img-blog.csdnimg.cn/img_convert/2aefe35bf1fbd79ad3215239cf4c497a.png)
从结果看,名字为“张三”的数据邮箱被修改,但是年龄被没有被修改仍然是34。解决方法有二个:
- 在属性上增加@TableField(updateStrategy = FieldStrategy.IGNORED)属性
@TableField(updateStrategy = FieldStrategy.IGNORED)
- 利用条件构造器中的Set方法
userMapper.update(null, Wrappers.lambdaUpdate().eq(User::getName,"张三") .set(User::getEmail,"zhangsannew@qq.com").set(User::getAge,null));
AR模式
AR模式简单的说就是直接用实体操作数据库
- 实体类继承Model类
@Data@TableName("sys_user")public class User extends Model {}
- 测试
@Testpublic void ar() { // 新增姓名为“大壮”的用户 User user = new User(); user.setName("大壮"); user.setAge(34); user.setEmail("dazhuang@qq.com"); user.setCreateTime(new Date()); user.insert(); // 查询姓名为大壮的数据 User repUser = user.selectOne(Wrappers.lambdaQuery().eq(User::getName,"大壮")); log.info("姓名为大壮的数据:{}",repUser);}
![3e4250e6aeb6ef9585dff2b231e2d07f.png](https://img-blog.csdnimg.cn/img_convert/3e4250e6aeb6ef9585dff2b231e2d07f.png)
姓名为“大壮”的用户新增成功,通过名字成功查询出来。
主键策略
Mybatis-plus主键策略大致可以分为五类
- AUTO:数据库ID自增
- NONE:该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)(只有当插入对象ID 为空,才自动填充)(默认的策略)
- INPUT:用户输入ID(该类型可以通过自己注册自动填充插件进行填充)
- ASSIGN_ID:分配ID(只有当插入对象ID 为空,才自动填充)
- ASSIGN_UUID:分配UUI(只有当插入对象ID 为空,才自动填充)
注:com.baomidou.mybatisplus.annotation.IdType.IdType.java定义主键策略类
下面将重点讲解一下NONE和ASSIGN_UUID策略。
测试默认主键策略NONE
- 实体类
@Data@TableName("sys_user")public class User extends Model { /** 主键 */ @TableId private String id;}
- 测试
@Testpublic void id1() { User user1 = new User(); user1.setName("王一"); user1.setAge(34); user1.setEmail("wangyi@qq.com"); user1.setCreateTime(new Date()); user1.insert(); User user2 = new User(); user2.setId("123456"); user2.setName("王二"); user2.setAge(34); user2.setEmail("wanger@qq.com"); user2.setCreateTime(new Date()); user2.insert(); log.info("用户【王一】id:{}",user1.getId()); log.info("用户【王二】id:{}",user2.getId());}
![996e3edbead23521d179e1ded7e5d022.png](https://img-blog.csdnimg.cn/img_convert/996e3edbead23521d179e1ded7e5d022.png)
从结果可以看出NONE为Mybatis-plus默认主键策略,并且当插入对象主键不为空时,不自动填充使用的是插入对象的值作为主键值,只有当插入对象ID 为空,才自动填充
测试ASSIGN_UUID实现
- 在实体中对id设置主键策略
@Data@TableName("sys_user")public class User extends Model { /** 主键 */ @TableId(type = IdType.ASSIGN_UUID) private String id;}
- 测试
@Testpublic void id2() { User user1 = new User(); user1.setName("小一"); user1.setAge(34); user1.setEmail("xiaoyi@qq.com"); user1.setCreateTime(new Date()); user1.insert(); User user2 = new User(); user2.setName("小二"); user2.setAge(34); user2.setEmail("xiaoer@qq.com"); user2.setCreateTime(new Date()); user2.insert(); log.info("用户【小一】id:{}",user1.getId()); log.info("用户【小二】id:{}",user2.getId());}
![2a6e853816cf8d702eb16cce95bc762b.png](https://img-blog.csdnimg.cn/img_convert/2a6e853816cf8d702eb16cce95bc762b.png)
从结果可以看出ASSIGN_UUID主键策略,采用的是UUID,只有当插入对象ID 为空,才自动填充
如果有哪里写得不对的,还请各位小友指正,只有不断试错,才能慢慢提高。如果你觉得对你有帮助,请点赞+关注,谢谢!!!!!!