Mybatis-Plus进阶
MP高级功能:
我们介绍以下七种高级功能:逻辑删除,自动填充,乐观锁插件,性能分析插件,多租户SQL解析器,动态表名SQL解析器,SQL注入器。
逻辑删除
1.逻辑删除简介
其实就是一种假删除的状态,修改数据库中的标记是否删除的字段,之后再数据库中仍然可以看到这条删除的记录
2.逻辑删除的实现
首先我们在application.yml中对mybatisplus的配置中设置逻辑删除和未删除的值:
mybatis-plus:global-config:db-config:logic-not-delete-value:0logic-delete-value:1//这也是MP的默认值,是一个全局配置
*接着我们写MyBatisPlus的配置类:
@Configuration
public class MyBatisPlusConfiguration{@Beanpublic ISqllnjector sqllnjector(){//在3.1.1版本开始,我们就不需要这一步配置了return new LogicSqllnjector ();}
}
在实体类的标记逻辑删除的变量上添加注解:
//这个注解中我们也可以传入逻辑生效或者未生效的值,是一个局部变量,只对当前实体生效
//一般情况下我们只设置全局的就可以
@TableLogic(delval="",value="")
private Integer deleted;
接下来我们进行测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class Test(){@Autowiredprivate UserMapper userMapper;@Testpublic void deleteById(){sout(userMapper.deleteById(87589347598123L));}
}
注意:MP在查询或者修改操作时会自动把逻辑删除标识加入where条件中,剔除已经删除的记录。
3.查询中排除删除标识字段及注意事项
我们可以在实体类的成员变量中加入注解来删除查询结果中的标识字段:
@TableLogic()
@TableField(select=false)
private Integer deleted
注意事项:在你自定义的语句中,MP不会给你添加带删除标识的where查询条件
UserMapper中:
@Select("select*from user ${ew.customSqlSegment}")
List<User> mySelectList(@Param(Constant.WRAPPER)Wrapper<User> wrapper);
Test类中
@Test
public void mySelect(){userMapper.mySelectList(Wrapper.<User>lambdaQuery().gt(User::getAge,25)).forEach(System.out::println);//会查询出全部年龄大于25的记录//我们可以自己添加where条件
}
自动填充
1.自动填充简介
有时候我们需要为像新增时间,修改时间,新增人,修改人这样的字段去自动填充值,这时候我们就可以使用MP为我们提供的自动填充功能
2.自动填充实现
1)首先我们为实体类中需要填充的字段加上注解:
@TableField(fill=FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill=FieldFill.UPDATE)
private LocalDateTime updateTime;
2)建立填充处理器实现MP提供的源对象处理器接口
@Component
public class MyMetaObjectHandler implements MetaObjectHandler{@Overridepublic void insertFill(MetaObject metaObject){//"createTime"是实体类中的属性名,不是数据库中的字段名。setInsertFieldValByName("createTime",LocalDateTime.now(),metaObject); }@Overridepublic void updateFill(MetaObject metaObject){//"updateTime"是实体类中的属性名,不是数据库中的字段名。setupdateFieldValByName("updateTime",LocalDateTime.now(),metaObject); }
}
3)进行测试
public class FillTest{@Autoeired
private UserMapper userMapper;@Test
public void insert(){User user = new User();user.setName("liumingchao");user.setAge(29);sout(userMapper.insert(user));
}
@Test
public void updateById(){User user = new User();user.setName("liumingchao");user.setAge(29);user.setId(123741273657818788L)sout(userMapper.updateById(user));
}
}
tips:有时候我们会在插入的数据库中碰到乱码的情况,我们只要在配置文件的数据库url配置中加入charactorEncoding=UTF-8
3.自动填充的优化
有时候我们要填充的值需要进行一系列方法调用才能获取到值,这些方法会产生一定的开销,因此我们可以通过处理器实现类中的metaObject对象配置哪些实体需要自动填充
@Component
public class MyMetaObjectHandler implements MetaObjectHandler{@Overridepublic void insertFill(MetaObject metaObject){boolean hasSetter = metaObjec.hasSeter("createTime");if(hasSetter){setInsertFieldValByName("createTime",LocalDateTime.now(),metaObject);} }
}
我们也可以判断在某个实体的属性为null时才自动填充
@Overridepublic void updateFill(MetaObject metaObject){Object val = getFieldValByName("updateTime",metaObject);if(val==null){setupdateFieldValByName("updateTime",LocalDateTime.now(),metaObject);}}
tips:如果你要自动填充的是新增人修改人,我们一般通过requestcontextholder对象的静态方法获取session中的user,再进行设置。
乐观锁插件
1.简介
当我们需要更新一条记录时,希望这条记录没有被别人更新过,是为了防止更新冲突
乐观锁的一种实现:1.取出记录时,获取当前version 2.更新时带上这个version 3.版本正确则更新成功,错误则失败
eg.
update user set name = '向南天',version = 3 where id = 413285719832718 and version = 2
乐观锁和悲观锁各有自己的应用场景,乐观锁适合写比较少的场景(多读场景),因为在多读场景即使有冲突也很少发生,这样会节省锁的开销,提高了系统的整体吞吐量,在多写的情况下,会经常产生冲突,就会导致上层应用不断进行重试,这样反倒会降低系统的性能,因此在这种场景下我们一般使用悲观锁。
2.功能实现
1)实现步骤
1.配置乐观锁插件
@Configuratin
public class MybatisPlusCongifuration{@Beanpublic OptimisticLockerInterceptor optimisticLockerInterceptor(){return new OptimisticLockerInterceptor();}
}
2.在记录版本的字段上添加注解
@Version
private Integer version;
3.测试
public class OptTest{@Testpublic void updateById(){int version = 1;User user = new User();user.setName("liumingchao");user.setAge(30);user.setId(123741273657818788L)user.SetVersion(version)sout(userMapper.updateById(user));}
}
2)注意事项
支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
整数类型下 newVersion = oldVersion + 1
newVersion 会回写到 entity 中
仅支持 updateById(id) 与 update(entity, wrapper) 方法
在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
性能分析插件
用来调sql语句和执行时间
1.性能分析实现
1)在配置类中添加性能分析插件
@Configuratin
public class MybatisPlusCongifuration{@Bean@Profile({"dev","test"})public PerformanceInterceptor performanceInterceptor(){PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor;//设置输出格式performanceInterceptor.setFormat(true);//配置慢sql的时长,超过这个时间会报错performanceInterceptor.setMaxTime(5L);return new PerformanceInterceptor();}
}
@Profile({“dev”,“test”})声明在开发环境和测试环境开启
2)右键,run as->run configuration->VM arguments设置-Dspring.profiles.active=dev才能看到效果
2.执行SQL分析打印
见MP官网
多租户SQL解析器
1.多租户概念介绍
多租户技术是一种软件架构技术,是实现如何在多用户环境下(此处的多用户一般是指面向企业的用户)共用相同的系统或者程序,并且确保用户间数据的隔离性。多租户一般有三种数据隔离方案,第一种是独立数据库,一个租户一个数据库,用户数据隔离级别最高,它的优点是为不同的租户提供了独立的数据库,有助于数据模型的扩展设计,满足不同租户的独特需求,如果出现故障,恢复数据比较简单,缺点是增加了数据库的数量,随之增加了维护成本和开销。第二种是共享数据库独立schema,这种方案的优点是为安全性要求较高的租户提供了一定程度的逻辑数据隔离,它并不是完全的隔离,每个数据库可支持更高的租户数量。缺点是如果出现了故障,数据库恢复比较困难,因为恢复数据库将涉及其它租户的数据库。第三种方案是共享数据库,共享schema,共享数据表,在表中增加租户id字段,这是共享程度最高,隔离级别最低的模式。优点是维护成本和购置成本最低,也允许每个数据库支持的租户最多,缺点是隔离级别最低,安全性最低。需要在设计开发时增加对安全的开发量,数据备份和恢复最困难甚至需要逐条备份和还原
2.多租户实现
多租户属于SQL解析部分,依赖MP分页插件,需要在分页插件中设置解析器。我们来实现上述的第三种方法。
1)在配置类中配置分页插件
@Configuratin
public class MybatisPlusCongifuration{@Beanpublic PaginationIterceptor paginationIterceptor(){PaginationIterceptor paginationIterceptor = new PaginationIterceptor();ArrayList<ISqlPaeser> sqlParserList = new ArrayList<ISqlPaeser>();TenantSqlParser tenantSqlParser = new TenantSqlParser();tenantSqlParser.setTenantHandler(new TenanrHandler)(){@Overridepublic String getTenantIdColunm(){return "manage_id";//表中的字段名}@Overridepublic Expression getTenantId(){return new LongValue(12378957169814598L)}@Override//过滤一些表public boolean doTableFilter(String tableName){if("role".equals(tableName)){return true;}return false;}});sqlParserList.add(tenantSqlParser);paginationIterceptor.setSqlParserList(sqlParserList);return paginationIterceptor;}
}
3.特定SQL过滤
1.在分页插件中配置过滤器
paginationIterceptor.setSqlParserFilter(new ISqlParserFilter(){@Overridepublic boolean doFilter(MetaObject metaObject){MappedStatement ms = SqlParserHelper.getMappedStatement(metaObject);//全限定名if("com.mp.dao.UserMapper.selectById".equals(ms.getId())){return true:}return false;}})
2.在UserMapper的方法上加上注解
@SqlParser(filter=true)
动态表名SQL解析器
1.动态表名的应用场景
有时候一个表数据量太大,我们进行分表存储,例如某些日志信息表,针对不同机构的表。我们查询这些表时需要动态生成表名。分库分表插件也可以解决这个问题。
2.动态表名的实现
我们也在分页插件的配置中配置
@Configuratin
public class MybatisPlusCongifuration{public static ThreadLocal<String> myTableName = new ThreadLocal<>();@Beanpublic PaginationIterceptor paginationIterceptor(){PaginationIterceptor paginationIterceptor = new PaginationIterceptor();ArrayList<ISqlPaeser> sqlParserList = new ArrayList<ISqlPaeser>();DynamicTableNameParser dynamicTableNameParser = new DynamicTableNameParser ();Map<String,ITableNameHandler> tableNameHandlerMap = new HashMap<String,ITableNameHandler>();tableNameHandlerMap.put("user",new ItableNameHandler(){@Overridepublic String dynamicTableName(MetaObject metaObject,String sql,String tableName){return myTableName.get();}});dynamicTableNameParser.setTableNameHandlerMap(tableNameHandlerMap);sqlParserList.add(dynamicTableNameParser);}
}
测试:
@Test
public void select(){MybatisPlusConfiguration.myTableName.set("user_2019");List<User> list = userMapper.selectList(null);list.forEach(System.out::println);
}
3.注意事项
1)我们在方法中不传MybatisPlusConfiguration.myTableName.set(“user_2019”) ,就不进行替换。
2)上面对多租户sql语句的过滤在这儿也会生效:
paginationIterceptor.setSqlParserFilter(new ISqlParserFilter(){@Overridepublic boolean doFilter(MetaObject metaObject){MappedStatement ms = SqlParserHelper.getMappedStatement(metaObject);//全限定名if("com.mp.dao.UserMapper.selectById".equals(ms.getId())){return true:}return false;}})
@SqlParser(filter=true)
SQL注入器
1.简介
使用它我们就可以自定义通用方法,就像selectById,insert这类方法,自定义的方法要添加到SQL注入器中,MP给我们提供的方法也是放在了SQL注入器中,在MP给我们提供的方法不能满足我们的需求时,我们可以自己注入。
2.实现步骤
1)创建定义方法的类
public class DeletaAllMethod extends AbstractMethod{@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass,Class<?> modelClass,TableInfo tableInfo){//执行的sqlString sql = "delete from" + tableInfo.getTableName();//mapper接口方法名String method = "deleteAll"Sqlsource sqlsource = langusgeDriver.createSqlSource(configuration,sql,modelClass);return addDeleteMappedStatement(mapperClass,method,sqlSource)}
}
2)创建注入器
@Component
public mySqlInjector extends DefaultSqlInjector{@Override
public List<AbstractMethod> getMethodList(Class<?> mapperClass){List<AbstrctMethod> methodList = super.getMathodList(mapperClass);methodList.add(new DeleteAllMethod());return methodList;
}
}
3)在Mapper中加入自定义方法
//删除所有,返回影响行数
int deleteAll();
4)测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class InjectorTest{@Autowiredprivate UserMapper userMapper;@Testpublic void deleteAll(){sout(userMapper.deleteAll());}
}
5)补充
我们不再去继承BaseMapper,继承我们自己的MyMapper,就不用在Mapper层中写我们自定义的方法了
public interface MyMapper<T> extends BaseMapper<T>{//删除所有,返回影响行数
int deleteAll();
}
注意:List methodList = super.getMathodList(mapperClass),不这样做我们就不能使用MP帮我们定义的方法了
MP帮我们提供了三个选装件,这三个选装件也是自定义方法
InsertBatchSomeColumn:批量新增数据,自选字段insert
LogicDeleteByIdWithFill:根据id逻辑删除数据,并带字段填充功能
alwaysUpdateSomeColumn:根据id更新固定的某些字段
Mybatis-Plus进阶相关推荐
- Day3-Mybatis基本框架搭建(添加用户)
Day3-Mybatis基本框架搭建(添加用户) 二. Mybatis-JDBC Mybatis的介绍 Mybatis的入门 使用jdbc操作数据库存在的问题 (回顾jdbc) Mybatis的架构 ...
- 基于SpringBoot+SpringCloud+Vue前后端分离项目实战 --开篇
本文目录 前言 做项目的三大好处 强强联手(天狗组合) 专栏作者简介 专栏的优势 后端规划 1. SpringBoot 和 SpringCloud 的选择 2. Mybatis 和 MybatisPl ...
- Java程序员的求职面试简历应该怎么写?Java常用框架有哪些?
[Java程序员]的求职面试简历应该怎么写?首先要做到信息的完整,比如基本信息.求职意向.工作经历/项目经验.个人技能这几大简历版块一定得有.然后简历内容要做到简单明了,详略得当.即要求大家简单概括自 ...
- aop拦截mybatis执行sql_Java进阶架构之开源框架面试题系列:Spring+SpringMVC+MyBatis
开源框架 Spring5 Framework体系结构 spring5概述 Spring5环境搭建 Spring MVC AOP源码解析 IOC源码解析 Mybatis spring 什么是Spring ...
- Java设计流程执行器_Java进阶面试精选系列:SpringMVC+SpringBoot+Hibernate+Mybatis+设计模式...
小编精心收集:为金三银四准备,以下面试题先过一遍,为即将到了的面试做好准备,也过一遍基础知识点. 一.Spring/Spring MVC 1.为什么要使用 spring? 2.解释一下什么是 aop? ...
- SpringBoot进阶教程 | 第四篇:整合Mybatis实现多数据源
这篇文章主要介绍,通过Spring Boot整合Mybatis后如何实现在一个工程中实现多数据源.同时可实现读写分离. 准备工作 环境: windows jdk 8 maven 3.0 IDEA 创建 ...
- mybatis多表查询出来的实体如何映射_mybatis进阶案例之多表查询
mybatis进阶案例之多表查询 一.mybatis中表之间的关系 在数据库中,实体型之间的关系主要有如下几种: 1.一对一 如果对于实体集A中的每一个实体,实体集B中至多有一个(也可以没有)实体与之 ...
- JavaWeb进阶之路:MyBatis初体验
JavaWeb进阶之路:MyBatis初体验 1. 简介 1.1 什么是MyBatis MyBatis 是一款优秀的持久层框架. 它支持自定义 SQL.存储过程以及高级映射. MyBatis 免除了几 ...
- MyBatis进阶——高级使用1
第一节:输入参数和输出参数 Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心. 1.1 环境准备 第一步:创建项目添加依赖 项 ...
- 【Java】Mybatis进阶篇(一)
Mybatis进阶篇 核心配置文件 1.mybatis-config.xml 2.Mybatis 的配置文件包含了会深深影响Mybatis行为的设置和属性信息 Configuration(配置) pr ...
最新文章
- linux内核编译练习
- 计算机科学导论 第4版,计算机科学导论.第4版
- bootstrap -- css -- 表单控件
- 1461B. Find the Spruce
- 关于安卓手机在微信浏览器中无法调起相机的原因
- 算法复习第六章第七章
- java 学习书籍 转载
- java计算奇数阶魔方阵
- linux和android学习,android学习笔记
- 通过自己的项目实际经验,阐述为什么“恶心玩技术”?玩Java开源B/S的教训(三)...
- android 好用的工具,android studio 的几个好用的工具
- CCF CSP 201703-1 分蛋糕
- Android Studio 利用系统签名打包apk
- linux查看 网卡信息
- python实验报告代写_programs作业代写、代做data课程作业、代写Python实验作业、Python编程设计作业调试...
- hone hone clock 与小松鼠驾到~还有牛顿摆等一些其他好玩的东西
- excel表格横向纵向变换_Excel操作技巧:简单3步,搞定数据统计和分析!
- 大乘起信论别记(本)
- c语言中,关于延迟函数的理解
- 星座查询-python
热门文章
- seo从入门到精通_SEO外包_seo技术教学案例培训学习研究中心自学网
- 计算机硬技术与基础在线测试,计算机硬件技术基础网上作业及答案
- 描写火车站场景_求几段描写火车站的段落,而且是描写的极好的段落
- Func:统一网络控制器
- VeryCD上的EIOffice 2009简介
- 站长引流工具 最新UI默笙站长工具箱V2.0 带后台
- 2021年施工员-土建方向-岗位技能(施工员)考试技巧及施工员-土建方向-岗位技能(施工员)实操考试视频
- 岛屿问题 通用解-463.岛屿周长-200.岛屿数量-695.岛屿的最大面积-827.最大人工岛
- 高通平台如何使用QPST抓DUMP
- slxrom+v.21+原生android+4.2,小米MIX2S 魔趣OS 安卓9 MagiskV21版 完美ROOT 纯净完美 原生极简 纯净推荐...