1. Mybaits-plus实战(三)

1.1. 特殊使用规则

1.1.1. Model逻辑删除

  1. 数据库对应实体类,继承Model类可以实现AR模式的sql语句操作,但这里需要注意的是,对逻辑删除,官方说明需要实现如下重写方法才能生效,也就是使用实例化对象.deleteById()
    @Override
protected Serializable pkVal() {
/**
* AR 模式这个必须有,否则 xxById 的方法都将失效!
* 另外 UserMapper 也必须 AR 依赖该层注入,有可无 XML
*/
return id;
}
  1. 事实上,在主键字段添加@TableId(value = "id", type = IdType.AUTO)该注解,效果等同上面
  2. 还要注意的,对逻辑删除字段不要加transient修饰词,否则逻辑删除也会不生效

1.1.2. MetaObjectHandler统一数据库操作数据处理

  1. 你可以在操作数据库前打印日志,也可以对即将输入的数据做修改
  2. 重要的是,如果你只是实现了这个接口实现类,并注入了Spring,对你修改的字段,返回前端的数据是会有修改的内容,但是插入或更新数据库是不存在的;这里你需要做的是在要进行插入或修改的字段上面加上注解@TableField(fill = FieldFill.INSERT),这里FieldFill有四种选择,如下,它默认是不做处理的,所以一定要填个
public enum FieldFill {
/**
* 默认不处理
*/
DEFAULT,
/**
* 插入填充字段
*/
INSERT,
/**
* 更新填充字段
*/
UPDATE,
/**
* 插入和更新填充字段
*/
INSERT_UPDATE
}
  1. 效果如下

1.1.3. 级联操作

  1. 对自定义语句条件用wrapper包装,实现多表联合查询也可以用链式的条件查询
  2. 例子基本都在下面了
//可直接在这里定义方法列表,默认只有在类上加注解才会支持方法
@QuerySupport("selectPageByCustomWithXml")
public interface UserMapper extends BaseMapper<User> { String JOIN_SQL = "SELECT user.*, role.name as role_name, role.create_time as role_create_time FROM user as user LEFT JOIN role as role ON user.role_id = role.id"; @QuerySupport
@Select("SELECT user.*, role.name as role_name, role.create_time as role_create_time FROM user as user LEFT JOIN role as role ON user.role_id = role.id")
List<UserRoleVO> findUserWithRoleByVoWithQueryList(@Param(Constants.WRAPPER) QueryWrapper<UserRoleVO> wrapper); @QuerySupport
@Select(JOIN_SQL)
List<User> selectListByCustom(@Param(Constants.WRAPPER) Wrapper<User> wrapper); /**
* 使用mybatis-plus自定义分页查询,使用resultMap将结果解析到关联对象中
*
* @param page 必须为第一个参数
* @param wrapper
* @return
*/
//类型优先级 (若未存在注解,当类型与mapper泛型不一致时使用其本身) @ResultType > @ResultMap > @Table(在类型一致时应用存在的resultMap)
@ResultMap("userCascadeResult")
@QuerySupport
@Select({"<script>", JOIN_SQL, "</script>"})
Page<User> selectPageByCustom(Page<User> page, @Param(Constants.WRAPPER) Wrapper<User> wrapper); @QuerySupport
Page<User> selectPageByCustomWithXml(Page<User> page, @Param(Constants.WRAPPER) Wrapper<User> wrapper); @QuerySupport
@Select({JOIN_SQL, "WHERE user.id = #{id}"})
User selectCascadeById(Serializable id); @ResultMap("userCascadeResult")
@Select({JOIN_SQL, "WHERE user.id = #{id}"})
User selectCascadeById2(Serializable id); @QuerySupport
@Select({"${text}"})
List<User> selectByText(@Param("text") String text, @Param(Constants.WRAPPER) Wrapper<User> wrapper); /**
* Wrapper支持select指定列的方式
* @param wrapper
* @return
*/
@QuerySupport
@Select("SELECT %s FROM user as user LEFT JOIN role as role ON user.role_id = role.id")
List<UserRoleVO> findUserWithRoleByVoWithQueryListAndColumns(@Param(Constants.WRAPPER) Wrapper<UserRoleVO> wrapper); @ResultMap("userNotCascadeResult")
@QuerySupport
@Select("SELECT %s FROM user")
Page<User> selectPageByCustomWithAssociationAndColumns(Page<User> page, @Param(Constants.WRAPPER) Wrapper<User> wrapper); }
     <select id="selectPageByCustomWithXml" resultMap="userCascadeResult">
SELECT user.*,
role.name as role_name,
role.create_time as role_create_time
FROM user as user
LEFT JOIN role as role
ON user.role_id = role.id
</select>

1.1.4. 增删改查技巧

  • 前提
    @Resource
private UserMapper mapper;
mapper.insert(
new User().setId(10086L)
.setName("miemie")
.setEmail("miemie@baomidou.com")
.setAge(3));
mapper.delete(new QueryWrapper<User>()
.lambda().eq(User::getName, "Sandy"))
mapper.update(
new User().setEmail("miemie@baomidou.com"),
new QueryWrapper<User>()
.lambda().eq(User::getId, 2)
);
User user = mapper.selectOne(new QueryWrapper<User>().lambda().eq(User::getId, 10086));

List<User> users = mapper.selectList(Wrappers.<User>query().orderByAsc("age"));

1.1.5. 查询去字段技巧

  1. 之前说过一个,通过加transient,利用jackson或fastjson,在返回前端的时候对它做处理去掉对应的字段,但同时我们又遇到个问题,比如del_flag,该字段往往前端不需要,但又不能加transient,原因上面也说了会导致逻辑删除功能失效,这时,还有个办法解决
  2. 在实体字段上加上注解@TableField(select = false),表示在进行sql查询时,去掉该字段的查询,这是在sql层面去掉该字段的查询,当然,如果你明确sql要查询这个字段还是可以查的
    /**
* 添加transient会导致逻辑删除模式失效
*/
@ApiModelProperty(value = "是否删除:0-正常 1-软删除")
@TableLogic
@TableField(select = false)
private Integer delFlag;

1.1.6. 子查询和嵌套查询

	System.out.println("----- 带子查询(sql注入) ------");
List<User> plainUsers2 = userMapper.selectList(new QueryWrapper<User>()
.inSql("role_id", "select id from role where id = 2"));
List<User> lambdaUsers2 = userMapper.selectList(new QueryWrapper<User>().lambda()
.inSql(User::getRoleId, "select id from role where id = 2"));
Assert.assertEquals(plainUsers2.size(), lambdaUsers2.size());
print(plainUsers2); System.out.println("----- 带嵌套查询 ------");
List<User> plainUsers3 = userMapper.selectList(new QueryWrapper<User>()
.nested(i -> i.eq("role_id", 2L).or().eq("role_id", 3L))
.and(i -> i.ge("age", 20)));
List<User> lambdaUsers3 = userMapper.selectList(new QueryWrapper<User>().lambda()
.nested(i -> i.eq(User::getRoleId, 2L).or().eq(User::getRoleId, 3L))
.and(i -> i.ge(User::getAge, 20)));
Assert.assertEquals(plainUsers3.size(), lambdaUsers3.size());
print(plainUsers3);
  • 查询结果的sql语句
----- 带子查询(sql注入) ------
SELECT id,name,age,email,role_id FROM user WHERE role_id IN (select id from role where id = 2) ----- 带嵌套查询 ------
SELECT id,name,age,email,role_id FROM user WHERE ( role_id = ? OR role_id = ? ) AND ( age >= ? )

1.2. 其它功能点(基本都是插件)

  1. 性能分析(sql执行时间)
  2. 乐观锁
  3. 分页
  4. 主键生成器
  5. 自定义sql
  6. 多租户

1.3. 总结

  • 其它功能点不是前面已经写过例子的,就是很少使用
  • 到现在我已经把mybatis-plus的所有官方文档和sample代码例子都看了一遍,也做了一些总结和特别标注,毕竟很多功能可能暂时用不到不代表以后用不到,在总结此篇的时候也让我对此前的博客有些技术上的修正,比如MetaObjectHandler的使用,并不是只能把值放返回对象,它是可以直接插入数据库的
  • mybatis-plus的总结工作到现在结束了,知识点应该已经概括了官方文档的所有,有啥意见建议请下面提_

Mybaits-plus实战(三)的更多相关文章

  1. coreseek实战(三):全文搜索在php中应用(使用api接口)

    coreseek实战(三):全文搜索在php中应用(使用api接口) 这一篇文章开始学习在php页面中通过api接口,使用coreseek全文搜索. 第一步:综合一下前两篇文章,coreseek实战( ...

  2. Python爬虫实战三之实现山东大学无线网络掉线自动重连

    综述 最近山大软件园校区QLSC_STU无线网掉线掉的厉害,连上之后平均十分钟左右掉线一次,很是让人心烦,还能不能愉快地上自习了?能忍吗?反正我是不能忍了,嗯,自己动手,丰衣足食!写个程序解决掉它! ...

  3. Thrift RPC实战(三) thrift序列化揭秘

    本文主要讲解Thrift的序列化机制, 看看thrift作为数据交换格式是如何工作的? 1.构造应用场景: 1). 首先我们先来定义下thrift的简单结构. 1 2 3 4 5 namespace ...

  4. miniFTP项目实战三

    项目简介: 在Linux环境下用C语言开发的Vsftpd的简化版本,拥有部分Vsftpd功能和相同的FTP协议,系统的主要架构采用多进程模型,每当有一个新的客户连接到达,主进程就会派生出一个ftp服务 ...

  5. 应用程序框架实战三十八:项目示例VS解决方案的创建(一)

    进行项目开发的第一步,是创建出适合自己团队习惯的VS解决方案,虽然我已经提供了项目示例,但毕竟是我创建的,你直接使用可能并不合适,另外你如果尝试模仿重新创建该示例,中间可能碰到各种障碍,特别是项目间的 ...

  6. 应用程序框架实战三十六:CRUD实战演练介绍

    从本篇开始,本系列将进入实战演练阶段. 前面主要介绍了一些应用程序框架的概念和基类,本来想把所有概念介绍完,再把框架内部实现都讲完了,再进入实战,这样可以让初学者基础牢靠.不过我的精力很有限,文章进度 ...

  7. 【SSH项目实战三】脚本密钥的批量分发与执行

    [SSH项目实战]脚本密钥的批量分发与执行 标签(空格分隔): Linux服务搭建-陈思齐 ---本教学笔记是本人学习和工作生涯中的摘记整理而成,此为初稿(尚有诸多不完善之处),为原创作品,允许转载, ...

  8. C# Redis实战(三)

    三.程序配置 在C# Redis实战(二)中我们安装好了Redis的系统服务,此时Redis服务已经运行. 现在我们需要让我们的程序能正确读取到Redis服务地址等一系列的配置信息,首先,需要在Web ...

  9. 汽车之家汽车品牌Logo信息抓取 DotnetSpider实战[三]

    一.正题前的唠叨 第一篇实战博客,阅读量1000+,第二篇,阅读量200+,两篇文章相差近5倍,这个差异真的令我很费劲,截止今天,我一直在思考为什么会有这么大的差距,是因为干货变少了,还是什么原因,一 ...

  10. Python爬虫实战三之爬取嗅事百科段子

    一.前言 俗话说,上班时间是公司的,下班了时间才是自己的.搞点事情,写个爬虫程序,每天定期爬取点段子,看着自己爬的段子,也是一种乐趣. 二.Python爬取嗅事百科段子 1.确定爬取的目标网页 首先我 ...

随机推荐

  1. Ocelot中文文档-认证

    为了验证ReRoutes并随后使用Ocelot的任何基于声明的功能,如授权或使用令牌中的值修改请求. 用户必须像往常一样在他们的Startup.cs中注册认证服务,但他们给每个注册提供了一个方案(认证 ...

  2. java反射机制,以及对反射机制的了解,如有差池欢迎点评(初学者勿喷)

    本人学习java时间不长,但是对java很感兴趣,知道有博客园这个平台果断的注册,记录我的java成长日记,这也是我的处女作,虽然很菜但是还是希望大家能见证我的成长,觉得可以的可以和我讨论一起学习 在 ...

  3. ImportError: cannot import name webdriver

    遇到问题: 学习selenium过程中为了方便自己知道学习的脚本的存放路径,以selenium命名 起初.py文件都在selenium文件夹下面,使用 from selenium import web ...

  4. 第一章 初识数据库Mysql

    初识数据库Mysql(my)   在企业中 percona: 一.数据库基础知识 Mysql是一个开放源代码的数据库管理系统(DBMS),它是由Mysql AB公司开发.发布并支持的.Mysql是一个 ...

  5. Python_驻留机制

    #coding=utf-8 #coding:utf-8 #- * -coding:utf-8 - * - '''以上为注明字符串的编码格式''' #驻留机制 '''Python支持短字符串驻留机制,对 ...

  6. Excel常用的格式处理

    你有没有碰到在Excel中设置了行高自适应后,部分行的行高太小,整体界面不美观的问题呢? 你有没有碰到Excel中的各个sheet页中的各列内容中都有不同个数的回车换行符,内容看起来参差不齐,不美观呢 ...

  7. Eclipse开发前,常用设置

    设置工作空间的项目编码, 防止出现乱码    Window - Preferences - General - Workspace    将"Text file encoding" ...

  8. 关于office在卸载了某一应用之后无法试图使用的功能所在的网络位置

    我出现这个问题是在卸载了某一个微软的办公软件之后,所有的办公软件都会产生这个问题. 处理的方法是将之前的安装包解压,然后找到所出现的msi文件,点击确定就ok了. 所以说,安装文件最好还是放在一个地方 ...

  9. 一个基于原生JavaScript开发的、轻量的验证码生成插件

    Vcode.js 一个基于原生JavaScript开发的.轻量的验证码生成插件 V: 1.0.0 DEMO:https://jofunliang.github.io/Vcode.js/example. ...

  10. ReenTrantLock可重入锁(和synchronized的区别)总结

    ReenTrantLock可重入锁(和synchronized的区别)总结 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也 ...