发布于2021-06-12 14:23 阅读(436) 评论(0) 点赞(17) 收藏(5)
根据 MybatisPlus 的 AutoSqlInjector 可以自定义各种你想要的 sql ,注入到全局中,相当于自定义 Mybatisplus 自动注入的方法。
之前需要在 xml 中进行配置的 SQL 语句,现在通过扩展 AutoSqlInjector 在加载 mybatis 环境时就注入。
1、在 Mapper 接口中定义相关的 CRUD 方法
public interface EmployeeMapper extends BaseMapper<Employee> {
int deleteAll();
}
2、扩展 AutoSqlInjector inject 方法,实现 Mapper 接口中方法要注入的 SQL
package com.ming.mp.injector;
import com.baomidou.mybatisplus.entity.TableInfo;
import com.baomidou.mybatisplus.mapper.AutoSqlInjector;
import org.apache.ibatis.builder.MapperBuilderAssistant;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.session.Configuration;
/**
* 自定义全局 sql注入操作
*/
public class MySqlInject extends AutoSqlInjector {
@Override
public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
super.inject(configuration, builderAssistant, mapperClass, modelClass, table);
//Mapper接口中定义的方法deleteAll()处理成MappedStatement对象、加入到configuration中
//1.注入SQL语句
String sql = "delete from " +table.getTableName();
//2.注入的方法名 与mapper接口中的方法名一致
String sqlMethod = "deleteAll";
//3.构建sqlSource对象
SqlSource sqlSource = languageDriver.createSqlSource(configuration,sql,modelClass);
//4.构建删除的MappedStatement对象
this.addDeleteMappedStatement(mapperClass,sqlMethod,sqlSource);
}
}
3、在MP全局策略中、配置自定义注入器
<!-- 定义MybatisPlus的全局策略配置-->
<bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 在2.3版本以后,dbColumnUnderline 默认值就是true 表名、字段名、是否使用下划线命名(默认 true: 数据库下划线命名) -->
<property name="dbColumnUnderline" value="true"></property>
<!-- 全局的主键策略 -->
<property name="idType" value="0"></property>
<!-- 全局的表前缀策略配置 -->
<property name="tablePrefix" value="tbl_"></property>
<!--注入自定义的全局操作-->
<property name="sqlInjector" ref="mySqlInject"/>
</bean>
<!--自定义SQL注入器-->
<bean id="mySqlInject" class="com.ming.mp.injector.MySqlInject"/>
测试:
private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
private EmployeeMapper employeeMapper = context.getBean("employeeMapper",EmployeeMapper.class);
@Test
public void testSqlInjector(){
int i = employeeMapper.deleteAll();
System.out.println(i);
}
报错:
Caused by: com.baomidou.mybatisplus.exceptions.MybatisPlusException: com.baomidou.mybatisplus.exceptions.MybatisPlusException: Error: Full table operation is prohibited. SQL: delete from tbl_employee
at com.baomidou.mybatisplus.plugins.SqlExplainInterceptor.sqlExplain(SqlExplainInterceptor.java:131)
at com.baomidou.mybatisplus.plugins.SqlExplainInterceptor.intercept(SqlExplainInterceptor.java:86)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
at com.sun.proxy.$Proxy19.update(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:49)
at com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor.intercept(OptimisticLockerInterceptor.java:71)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
at com.sun.proxy.$Proxy19.update(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:49)
at com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor.intercept(OptimisticLockerInterceptor.java:71)
at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
at com.sun.proxy.$Proxy19.update(Unknown Source)
at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:198)
... 34 more
报错原因:因为使用了注册执行分析插件,将他注释掉
<bean class="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor">
<!--作用就是我发现了当前你的操作是全表删除或更新、会阻止你的操作-->
<property name="stopProceed" value="true"/>
</bean>
MP启动的时候会加载MappedStatement
DEBUG 06-08 22:58:57,285 addMappedStatement: com.ming.mp.mapper.EmployeeMapper.deleteAll (MybatisConfiguration.java:67)
假删除、逻辑删除:并不会真正的从数据库中将数据删除掉,而是将当前被删除的这条数据中的一个逻辑删除字段置为删除状态
update tbl_user set logic_flag = 1 → -1
步骤:
1、com.baomidou.mybatisplus.mapper.LogicSqlInjector
<!-- 定义MybatisPlus的全局策略配置-->
<bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 在2.3版本以后,dbColumnUnderline 默认值就是true 表名、字段名、是否使用下划线命名(默认 true: 数据库下划线命名) -->
<property name="dbColumnUnderline" value="true"></property>
<!-- 全局的主键策略 -->
<property name="idType" value="0"></property>
<!-- 全局的表前缀策略配置 -->
<property name="tablePrefix" value="tbl_"></property>
<!--注入自定义的全局操作-->
<!-- <property name="sqlInjector" ref="mySqlInject"/>-->
<!--注入逻辑删除-->
<property name="sqlInjector" ref="logicSqlInjector"/>
</bean>
<!--逻辑删除-->
<bean id="logicSqlInjector" class="com.baomidou.mybatisplus.mapper.LogicSqlInjector"/>
<!--自定义SQL注入器-->
<bean id="mySqlInject" class="com.ming.mp.injector.MySqlInject"/>
2、logicDeleteValue 逻辑删除全局值
<!-- 逻辑删除全局值为-1-->
<property name="logicDeleteValue" value="-1"></property>
3、logicNotDeleteValue 逻辑未删除全局值
<!-- 定义MybatisPlus的全局策略配置-->
<bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 在2.3版本以后,dbColumnUnderline 默认值就是true 表名、字段名、是否使用下划线命名(默认 true: 数据库下划线命名) -->
<property name="dbColumnUnderline" value="true"></property>
<!-- 全局的主键策略 -->
<property name="idType" value="0"></property>
<!-- 全局的表前缀策略配置 -->
<property name="tablePrefix" value="tbl_"></property>
<!--注入SQL自定义的全局操作-->
<!-- <property name="sqlInjector" ref="mySqlInject"/>-->
<!--注入逻辑删除-->
<property name="sqlInjector" ref="logicSqlInjector"/>
<!--注入逻辑删除的全局值-->
<!-- 逻辑删除全局值为-1就是删除状态-->
<property name="logicDeleteValue" value="-1"></property>
<!--逻辑未删除全局值为1未删除状态-->
<property name="logicNotDeleteValue " value="1"></property>
</bean>
4、在 POJO 的逻辑删除字段 添加 @TableLogic 注解
public class User {
private Integer id;
private String name;
@TableLogic
private Integer logicFlag;//逻辑删除属性
}
5、会在 mp 自带查询和更新方法的 sql 后面,追加[逻辑删除字段]=[LogicNotDeleteValue默认值]
删除方法: deleteById()和其他 delete 方法, 底层 SQL 调用的是 update tbl_XXX set [逻辑删除字段] =[LogicNotDeleteValue默认值]
逻辑删除测试
@Test
public void testLogicDelete(){
int i = userMapper.deleteById(1);
System.out.println(i);
}
DEBUG 06-08 23:52:15,864 ==> Preparing: UPDATE tbl_user SET logic_flag=-1 WHERE id=? (BaseJdbcLogger.java:159)
DEBUG 06-08 23:52:15,884 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:159)
DEBUG 06-08 23:52:15,886 <== Updates: 1 (BaseJdbcLogger.java:159)
Time:6 ms - ID:com.ming.mp.mapper.UserMapper.deleteById
Execute SQL:
UPDATE
tbl_user
SET
logic_flag=-1
WHERE
id=1]
DEBUG 06-08 23:52:15,890 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@769a1df5] (SqlSessionUtils.java:191)
DEBUG 06-08 23:52:15,890 Returning JDBC Connection to DataSource (DataSourceUtils.java:327)
1
逻辑删除后–查询测试查询不到结果的
@Test
public void testLogicDelete(){
// int i = userMapper.deleteById(1);
// System.out.println(i);
User user = userMapper.selectById(1);
System.out.println(user);
}
DEBUG 06-08 23:58:59,350 ==> Preparing: SELECT id,`name`,logic_flag AS logicFlag FROM tbl_user WHERE id=? AND logic_flag=1 (BaseJdbcLogger.java:159)
DEBUG 06-08 23:58:59,370 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:159)
DEBUG 06-08 23:58:59,378 <== Total: 0 (BaseJdbcLogger.java:159)
Time:11 ms - ID:com.ming.mp.mapper.UserMapper.selectById
Execute SQL:
SELECT
id,
`name`,
logic_flag AS logicFlag
FROM
tbl_user
WHERE
id=1
AND logic_flag=1]
DEBUG 06-08 23:58:59,381 Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@769a1df5] (SqlSessionUtils.java:191)
DEBUG 06-08 23:58:59,381 Returning JDBC Connection to DataSource (DataSourceUtils.java:327)
null
com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
公共字段填充:比如我们插入修改操作有一些字段没有提供值,我们希望有一些默认的值填充上去
public abstract void insertFill(MetaObject metaObject);
public abstract void updateFill(MetaObject metaObject);
MetaObject :元对象、它是mybatis提供的一个用于更加方便访问对象的属性、给对象的属性设置值的一个对象。还会用于包装我们的对象,支持object,mapper,collection对象等进行包装
本质上MetaObject 获取对象的属性值,或者给对象的属性设置值是要底层最终要通过rflector反射获取我们属性对应的方法的Invoker,最终Invoker.
1、注解填充字段注解填充字段 @TableField(… fill = FieldFill.INSERT) 查看FieldFill
有时候开发的时候不会提供该字段值,我们提供一个默认值,name为公共字段填充
public class User {
private Integer id;
@TableField(fill = FieldFill.INSERT_UPDATE)
private String name;
}
2、自定义公共字段填充处理器
package com.ming.mp.beans.metaobject;
import com.baomidou.mybatisplus.mapper.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
/**
* 自定义公共字段填充处理器
*/
public class MyMetaObject extends MetaObjectHandler {
/**
* 插入操作自动填充
*
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
//获取到需要被填充的字段值
Object fieldValByName = getFieldValByName("name", metaObject);
if (fieldValByName == null) {
System.out.println("*********插入操作,满足填充条件**********");
setFieldValByName("name","公共字段填充的名字",metaObject);
}
}
/**
* 修改操作自动填充
*
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
//获取到需要被填充的字段值
Object fieldValByName = getFieldValByName("name", metaObject);
if (fieldValByName == null) {
System.out.println("*********修改操作,满足填充条件**********");
setFieldValByName("name","公共字段填充的名字",metaObject);
}
}
}
3、MP全局注入 自定义公共字段填充处理器
<!-- 定义MybatisPlus的全局策略配置-->
<bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 在2.3版本以后,dbColumnUnderline 默认值就是true 表名、字段名、是否使用下划线命名(默认 true: 数据库下划线命名) -->
<property name="dbColumnUnderline" value="true"></property>
<!-- 全局的主键策略 -->
<property name="idType" value="0"></property>
<!-- 全局的表前缀策略配置 -->
<property name="tablePrefix" value="tbl_"></property>
<!--注入自定义的全局操作-->
<!-- <property name="sqlInjector" ref="mySqlInject"/>-->
<!--注入逻辑删除-->
<property name="sqlInjector" ref="logicSqlInjector"/>
<!--注入逻辑删除的全局值-->
<!-- 逻辑删除全局值为-1就是删除状态-->
<property name="logicDeleteValue" value="-1"></property>
<!--逻辑未删除全局值为1未删除状态-->
<property name="logicNotDeleteValue" value="1"></property>
<!--注入自定义公共字段填充处理器-->
<property name="metaObjectHandler" ref="myMetaObject"/>
</bean>
<!--自定义公共字段填充处理器-->
<bean id="myMetaObject" class="com.ming.mp.beans.metaobject.MyMetaObject"/>
测试:插入的name字段是我们定义的公共字段填充的值、
@Test
public void testMetaObjectHandler() {
User user = new User();
user.setLogicFlag(1);
userMapper.insert(user);
}
DEBUG 06-09 22:45:09,072 Fetching JDBC Connection from DataSource (DataSourceUtils.java:110)
DEBUG 06-09 22:45:09,072 JDBC Connection [com.mchange.v2.c3p0.impl.NewProxyConnection@6ca18a14 [wrapping: com.mysql.jdbc.JDBC4Connection@c667f46]] will not be managed by Spring (SpringManagedTransaction.java:87)
DEBUG 06-09 22:45:09,076 ==> Preparing: INSERT INTO tbl_user ( `name`, logic_flag ) VALUES ( ?, ? ) (BaseJdbcLogger.java:159)
DEBUG 06-09 22:45:09,097 ==> Parameters: 公共字段填充的名字(String), 1(Integer) (BaseJdbcLogger.java:159)
DEBUG 06-09 22:45:09,100 <== Updates: 1 (BaseJdbcLogger.java:159)
Time:8 ms - ID:com.ming.mp.mapper.UserMapper.insert
Execute SQL:
INSERT
INTO
tbl_user
( `name`, logic_flag )
VALUES ( '公共字段填充的名字', 1 )]
原文链接:https://blog.csdn.net/qq_29445811/article/details/117716281
作者:天花灯
链接:http://www.javaheidong.com/blog/article/222335/8b065840030c10064dac/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!