MybatisPlus学习笔记9:自定义全局操作
1、AutoSqlInjector :
BaseMapper提供了17个常用方法,但是有些需求这些方法还是不能很好的实现,那么怎么办呢?
大家肯定会想到是在xml文件中写sql语句解决。
这样确实可以,因为MP是只做增强不做改变,我们完全可以按照mybatis的原来的方式来解决。
不过MP也提供了另一种解决办法,那就是自定义全局操作。
所谓自定义全局操作,也就是我们可以在mapper中自定义一些方法,然后通过某些操作,让自定义的这个方法也能像BaseMapper的内置方法,供全局调用。
接下来就看看如何实现(以deleteAll方法为例)。
1.1在mapper中定义方法
public interface EmplopyeeDao extends BaseMapper<Employee> {
int deleteAll();
}
public interface UserDao extends BaseMapper<User> {
int deleteAll();
}
在这两个mapper接口中都定义了deleteAll方法。
1.2 编写自定义注入类
该类继承AutoSqlInjector,重写inject方法。
然后编写sql语句,指定mapper接口中的方法,最后调用addDeleteMappedStatement方法即可。
public class MySqlInjector extends AutoSqlInjector {
@Override
public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant,
Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
/* 添加一个自定义方法 */
deleteAllUser(mapperClass, modelClass, table);
System.out.println(table.getTableName());
}
public void deleteAllUser(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
/* 执行 SQL ,动态 SQL 参考类 SqlMethod */
String sql = "delete from " + table.getTableName();
/* mapper 接口方法名一致 */
String method = "deleteAll";
SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
this.addDeleteMappedStatement(mapperClass, method, sqlSource);
}
}
1.3 在Spring文件中配置
先把刚才自定义的类注册成bean,然后在全局策略配置的bean中引用自定义类的bean即可。
<!-- 定义自定义注入器 -->
<bean class="com.zhu.mybatisplus.injector.MySqlInjector" id="mySqlInjector"/>
..........
<!-- 5、mybatisplus的全局策略配置 -->
<bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<property name="idType" value="0"/>
<property name="tablePrefix" value="tb_"/>
<!-- 注入自定义全局操作 -->
<property name="sqlInjector" ref="mySqlInjector"/>
</bean>
1.4 测试
经测试,当userDao调用deleteAll方法时,会删除tb_user表的所有数据,employeeDao调用deleteAll方法时,会删除tb_employee表的所有数据。
说明deleteAll方法是有效的。
不过在运行这两个测试时,由于是全表删除操作,所有要先把执行分析插件关了。
@Test
public void testMySqlInjector(){
Integer result = userDao.deleteAll();
System.out.println(result);
}
@Test
public void testMySqlInjector2(){
Integer result = emplopyeeDao.deleteAll();
System.out.println(result);
}
2、逻辑删除
其实数据并不会轻易的删除掉,毕竟数据收集不易,所以就有了逻辑删除。
逻辑删除: 并不会真正的从数据库中将数据删除掉,而是将当前被删除的这条数据中的一个逻辑删除字段置为删除状态,
比如该数据有一个字段logic_flag,当其值为1表示未删除,值为-1表示删除,那么逻辑删除就是将1变成-1。
2.1 数据表
在数据表中需要添加逻辑删除字段(logic_flag)
2.2 实体类
数据库中逻辑删除字段是logic_flag,所以实体类中的logicFlag需要用@TableLogic注解标记。
@Data
public class User{
private Integer id;
private String name;
private Integer age;
private Integer gender;
@TableLogic //标记逻辑删除属性
private Integer logicFlag;
}
2.3 mapper
public interface UserDao extends BaseMapper<User> {
}
2.4 需要在spring-dao.xml中做如下配置:
首先定义逻辑删除的bean:
<!-- 逻辑删除 -->
<bean class="com.baomidou.mybatisplus.mapper.LogicSqlInjector" id="logicSqlInjector"/>
再在全局配置的bean中注入逻辑删除以及逻辑删除值:
<!-- 5、mybatisplus的全局策略配置 -->
<bean id="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
<!-- 此处省略其他全局配置 -->
<!-- 注入自定义全局操作,做逻辑删除时需要先注释掉 -->
<!--<property name="sqlInjector" ref="mySqlInjector"/>-->
<!-- 注入逻辑删除,先要把自定义的注释掉 -->
<property name="sqlInjector" ref="logicSqlInjector"/>
<!-- 注入逻辑删除值 -->
<property name="logicDeleteValue" value="-1"/><!-- -1是删除状态 -->
<property name="logicNotDeleteValue" value="1"/><!-- 1是未删除状态 -->
</bean>
因为逻辑删除实际上也是一个sqlInjector,所以先要把刚才做自定义全局操作时注入的自定义全局操作注释掉,上面代码中已有详细注释说明。
2.5 测试
@Test
public void testLogicDelete(){
Integer result = userDao.deleteById(1);
System.out.println(result);
//User user = userDao.selectById(1);
//System.out.println(user);
}
运行该测试,执行删除操作的时候,真正执行的sql语句是UPDATE tb_user SET logic_flag=-1 WHERE id=?,就是把逻辑删除字段的值设置为-1;
当逻辑删除字段的值是-1时再执行查询操作,sql是SELECT ... FROM tb_user WHERE id=? AND logic_flag=1,所以查询结果是null。