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。

posted @ 2020-04-15 22:28  xidianzxm  阅读(906)  评论(0编辑  收藏  举报