Data Access 之 MyBatis Plus(五)- 自定义 BaseMapper

2022-08-19 17:53:04 浏览数 (1)

一、自定义通用方法TeslaDeleteAll

MyBatis Plus支持自定义通用方法,自定义通用方法与MP自带的通用方法一样,都会在应用启动时将方法注入到全局中

自定义通用方法的步骤:

  1. 在XxxMapper中定义想要自定义的通用方法,XxxMapper要继承BaseMapper
  2. 创建一个类继承AbstractMethod,重写injectMappedStatement()方法,该方法中输入写自定义通用方法的SQL语句
  3. 创建一个XxxInjector类继承DefaultInjector,重写getMethodList()方法,该方法中将包含了自定义SQL语句的类的实例化对象添加到methodList中
  4. 在配置文件中通过bean标签配置自定义的XxxInjector,并在全局配置中通过属性sqlInjector引入

自定义 BaseMappper

1. 在TeslaMapper中定义deleteAll()方法
代码语言:javascript复制
public interface TeslaMapper extends BaseMapper<Tesla> {

    int deleteAll();
}
2. 创建TeslaDeleteAll类,继承AbstractMethod类,定义SQL语句
代码语言:javascript复制
public class TeslaDeleteAll extends AbstractMethod {

    // 将deleteAll()处理成对应的MappedStatement对象,加入到configuration对象中
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        /* 执行 SQL ,动态 SQL 参考类 SqlMethod */
        String sql = "delete from "   tableInfo.getTableName();
        /* mapper 接口方法名一致 */
        String method = "deleteAll";
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addDeleteMappedStatement(mapperClass, method, sqlSource);
    }
}
3. 创建一个TeslaSqlInjector类,继承DefaultSqlInjector类
代码语言:javascript复制
public class TeslaSqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
         List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
         methodList.add(new TeslaDeleteAll());
         return methodList;
    }
}
4. 在全局配置文件中配置TeslaSqlInjector
代码语言:javascript复制
<!--将DB配置注入全局配置-->
<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
    <property name="dbConfig" ref="dbConfig"/> <!--  非必须  -->
    <!--配置自定义注入器-->
    <property name="sqlInjector" ref="teslaSqlInjector"></property>
</bean>
<!--&amp;lt;!&amp;ndash;定义自定义的注入器&amp;ndash;&amp;gt;-->
<bean id="teslaSqlInjector" class="com.lilith.injector.TeslaSqlInjector"></bean>
5. 测试自定义通用方法

在TeslaMapperTest中增加testTeslaDeleteAll()方法

代码语言:javascript复制
@Test
public void testTeslaDelteAll(){
    teslaMapper.deleteAll();
}

自定义的通用方法生效

可以参考 MyBatis Plus 示例项目

二、MP逻辑删除注入器的使用

逻辑删除既假删除,并不是真正的从数据库中删除,而是将当前被删除的这条数据中的一个逻辑删除字段改为删除状态。

首先在t_tesla表增加logic_flag字段,并设置所有记录的logic_flag值为0,表示未删除;接着在Tesla实体类中增加logicFlag属性以及响应的getter/setter方法,并该字段属性上增加@TableLogic注解

在配置文件中配置逻辑删除字段、逻辑已删除值、逻辑未删除值

代码语言:javascript复制
<bean id="dbConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig">
    <!--全局配置主键策略,AUTO或者索引0-->
    <property name="idType" value="AUTO"></property>
    <!--配置统一表名前缀-->
    <property name="tablePrefix" value="t_" />
    <property name="logicDeleteField" value="logic_flag" />
    <!--逻辑已删除值-->
    <property name="logicDeleteValue" value="1" />
    <!--逻辑未删除值-->
    <property name="logicNotDeleteValue" value="0" />
</bean>

在TeslaMapperTest中增加逻辑删除的测试方法

代码语言:javascript复制
@Test
public void testLoginDelete(){

    int count = teslaMapper.deleteById(1166057520);
    System.out.println(count);
}

执行测试

虽然执行的方法是删除方法,但实际执行的是UPDATE方法,将逻辑删除字段从0 改为 1,再次增加一个测试方法,查询已经逻辑删除的数据

代码语言:javascript复制
@Test
public void testSelectByIdWithLogicDelete(){
    Tesla tesla = teslaMapper.selectById(1166057520);
    System.out.println("查询到的已经被逻辑删除的数据为:"   tesla);
}

查询已经被逻辑删除的字段的查询结果为空,执行查询时带上逻辑删除字段作为查询条件,但仅限于BaseMapper中自带的方法

关于逻辑删除的使用也可以参考MP官网的 逻辑删除

三、MP 自动填充功能

在进行插入或者修改操作的时候,有些字段没有提供值的情况下,希望能有默认值进行填充,实现元对象处理器接口是com.baomidou.mybatisplus.core.handlers.MetaObjectHandler,该接口可以实现公共字段自动写入

metaObject:元对象,是MyBatis提供的一个用于更加方便优雅的访问对象的属性,给对象的属性设置一个对象,还可用于包装对象,支持Object、Map、Collection对象进行包装,本质上metaObject获取对象的属性值或者是给对象的属性设置值,最终是要通过Reflector获取到属性的对应方法的invoker,通过放射获取对象

实现公共字段自动填充步骤

1. 在Tesla实体类上给需要进行自动填充的属性增加@TableField注解
代码语言:javascript复制
@TableField(fill = FieldFill.INSERT_UPDATE)
private String factory;

FieldFill是一个枚举类,共有四种枚举值

起始就是设置删除或者更新时进行自动填充或者默认或者删除和更新时都进行自动填充

2. 自定义公共字段填充处理器

自定义的公共字段填充器需要实现MetaObjectHandler接口,并实现两个方法,既执行INSERT和UPDATE是自动填充的字段和字段值

代码语言:javascript复制
public class TeslaMetaObjectHandler implements MetaObjectHandler {

    // 插入操作自动填充
    @Override
    public void insertFill(MetaObject metaObject) {
        // 获取需要被填充的字段的值
        Object fieldVal = getFieldValByName("factory", metaObject);
        if (fieldVal == null){
            setFieldValByName("name", "柏林特斯拉超级工厂", metaObject);
        }
    }
    // 更新操作自定填充
    @Override
    public void updateFill(MetaObject metaObject) {
        // 获取需要被填充的字段的值
        Object fieldVal = getFieldValByName("factory", metaObject);
        if (fieldVal == null){
            setFieldValByName("name", "弗拉蒙特特斯拉超级工厂", metaObject);
        }
    }
}
3. 全局注入自定义的公共字段填充处理器

将自定义的字段填充器加入到容器中,并添加到全局配置中

代码语言:javascript复制
<!--将DB配置注入全局配置-->
<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
    <property name="dbConfig" ref="dbConfig"/> <!--  非必须  -->
    <!--配置自定义注入器-->
    <property name="sqlInjector" ref="teslaSqlInjector"></property>
    <property name="metaObjectHandler" ref="teslaMetaObjectHandler"></property>
</bean>
<bean id="teslaMetaObjectHandler" class="com.lilith.meta.TeslaMetaObjectHandler">
</bean>
4. 测试自定义公共字段填充器
代码语言:javascript复制
@Test
public void testInsertByTeslaAutoFillHandler(){
    Tesla tesla = new Tesla();
    tesla.setLogicFlag(0);

    teslaMapper.insert(tesla);
}

在没有设置factory字段的情况下执行插入时自动填充factory字段的值为柏林特斯拉超级工厂

代码语言:javascript复制
@Test
public void testUpdateByTeslaAutoFillHandler(){
    Tesla tesla = new Tesla();
    tesla.setId(1166057539);
    tesla.setName("Roadster 2022");
    tesla.setPrice(1300000.00);

    teslaMapper.updateById(tesla);
}

在没有设置factory字段值进行更新时,也会为factory自定填充值

代码语言:javascript复制
@Test
public void testInsertByTeslaAutoFillHandlerWithValue(){
    Tesla tesla = new Tesla();
    tesla.setLogicFlag(0);
    tesla.setFactory("得克萨斯州特斯拉超级工厂");

    teslaMapper.insert(tesla);
}

factory字段有值的情况下,使用给定的值

对于添加了@TableFiled注解的属性,使用MP通用方法更新时如果保持属性不变,也需要对属性的Value进行set操作,否则会设置成自动填充处理器中的值

也可以参考MP 官网的 自动填充功能

至此,MyBatis Plus 完结✿✿ヽ(°▽°)ノ✿

0 人点赞