mybatis的使用及源码分析(十四) Mybatis-Plus自定义通用方法

本文介绍如何在Mybatis-Plus中自定义通用方法,包括创建自定义方法枚举、实现自定义方法、构建自定义SQL注入器及通用Mapper等步骤。通过这些自定义功能,可以扩展Mybatis-Plus的功能并更好地满足项目需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

Mybatis-Plus中提供了很多通用方法,可以参见DefaultSqlInjector类,如下:

public class DefaultSqlInjector extends AbstractSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        return Stream.of(
            new Insert(),
            new Delete(),
            new DeleteByMap(),
            new DeleteById(),
            new DeleteBatchByIds(),
            new Update(),
            new UpdateById(),
            new SelectById(),
            new SelectBatchByIds(),
            new SelectByMap(),
            new SelectOne(),
            new SelectCount(),
            new SelectMaps(),
            new SelectMapsPage(),
            new SelectObjs(),
            new SelectList(),
            new SelectPage()
        ).collect(toList());
    }
}

我们也可以自定义一些通用方法,定义继承BaseMapper的通用Mapper,实现自己的通用方法。

一、自定义方法枚举

package com.iscas.biz.mp.enhancer.enums;

/**
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2021/12/23 14:09
 * @since jdk1.8
 */
public enum CustomSqlMethod {

    /**
     * truncate
     * */
    TRUNCATE("truncate", "truncate一张表", "<script>\nTRUNCATE TABLE %s \n</script>");
    
    private final String method;
    private final String desc;
    private final String sql;

    CustomSqlMethod(String method, String desc, String sql) {
        this.method = method;
        this.desc = desc;
        this.sql = sql;
    }

    public String getMethod() {
        return method;
    }

    public String getDesc() {
        return desc;
    }

    public String getSql() {
        return sql;
    }
}

二、自定义方法

package com.iscas.biz.mp.enhancer.injector.methods;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.iscas.biz.mp.enhancer.enums.CustomSqlMethod;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

/**
 * truncate表
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2021/12/23 13:57
 * @since jdk1.8
 */
public class TruncateMethod extends AbstractMethod {
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        CustomSqlMethod sqlMethod = CustomSqlMethod.TRUNCATE;
        String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName());
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource);
    }
}

三、自定义SQL注入器

package com.iscas.biz.mp.enhancer.injector;

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
import com.iscas.common.tools.core.io.file.ScannerUtils;
import com.iscas.common.tools.exception.lambda.Lambdas;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 自定义SQL注入器
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2021/12/23 14:18
 * @since jdk1.8
 */
 @Component
public class CustomSqlInjector extends DefaultSqlInjector {
    private volatile List<AbstractMethod> methodCache;
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        if (methodCache == null) {
            synchronized (CustomSqlInjector.class) {
                if (methodCache == null) {
                    List<AbstractMethod> methodList = super.getMethodList(mapperClass);
                    methodList.addAll(getCustomMethods());
                    methodCache = methodList;
                }
            }
        }
        return methodCache;
    }

    /**
     * 获取methods包下的所有方法类,并实例化
     */
    private List<? extends AbstractMethod> getCustomMethods() {
        String methodsPackageName = CustomSqlInjector.class.getPackageName() + ".methods";
        return ScannerUtils.getClasses(methodsPackageName)
                .stream().filter(AbstractMethod.class::isAssignableFrom)
                .map(Lambdas.wrapperFunction(clazz -> (AbstractMethod) clazz.getDeclaredConstructor().newInstance()))
                .collect(Collectors.toList());
    }
    
}

注意的是如果使用的mybatis-plus-boot-starter依赖,上面这样写就可以了。如果没有使用mybatis-plus的自动配置依赖,需要在SqlSessionFactory中添加GlobalConfig,GlobalConfig中添加Sql注入器。

@Primary
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
        factory.setDataSource(dataSource);

        MybatisConfiguration configuration = new MybatisConfiguration();
        //configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
        configuration.setJdbcTypeForNull(JdbcType.NULL);
        configuration.setMapUnderscoreToCamelCase(true);
        configuration.setCacheEnabled(false);
        factory.setConfiguration(configuration);
        PaginationInnerInterceptor paginationInnerInterceptor = paginationInterceptor();
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        factory.setPlugins(interceptor);
        if (StringUtils.isNotBlank(enumPackages)) {
            factory.setTypeEnumsPackage(enumPackages);
        }
        factory.setGlobalConfig(globalConfiguration());
        factory.setTransactionFactory(new MultiDataSourceTransactionFactory());
        //mapper config path
        String mpMapperLocations = environment.getProperty("mp.mapper.locations");
        if (StringUtils.isNotEmpty(mpMapperLocations)) {
            Arrays.stream(mpMapperLocations.split(","))
                    .forEach(location -> {
                        try {
                            factory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(location));
                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    });
        }
        return factory.getObject();
    }
    private GlobalConfig globalConfiguration() {
        GlobalConfig conf = GlobalConfigUtils.defaults();
        conf.getDbConfig().setIdType(IdType.valueOf(idType));
        conf.setSqlInjector(new CustomSqlInjector());
        return conf;
    }

四、自定义通用Mapper

package com.iscas.biz.mp.enhancer.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.iscas.biz.mp.aop.enable.ConditionalOnMybatis;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.ResultSetType;
import org.apache.ibatis.session.ResultHandler;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;

/**
 * 执行SQL语句的Mapper
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2018/9/27 10:23
 * @since jdk1.8
 */
@Repository
@ConditionalOnMybatis
public interface DynamicMapper<T> extends BaseMapper<T> {

    /**
     * 扩展Mybatis-Plus的方法
     * truncate
     * */
    void truncate();
}

五、测试

package com.iscas.biz.mp.test.model;

import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

/**
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2020/3/26 13:46
 * @since jdk1.8
 */
@Data
public class Test {
    @TableId(type = IdType.AUTO)
    private Integer id;

    private String name;

    @TableField(updateStrategy = FieldStrategy.IGNORED)
    private Integer age;

}

package com.iscas.biz.mp.test.mapper;

import com.iscas.biz.mp.enhancer.mapper.DynamicMapper;
import com.iscas.biz.mp.test.model.Test;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

/**
 *
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2020/3/26 14:08
 * @since jdk1.8
 */
@Repository
@Mapper
public interface TestMapper extends DynamicMapper<Test> {
}


/**
 * @author zhuquanwen
 * @vesion 1.0
 * @date 2020/3/26 14:09
 * @since jdk1.8
 */
@RestController
@RequestMapping("/test/mybatis/plus")
@ConditionalOnMybatis
public class TestController extends BaseController {

    @Autowired
    private TestMapper testMapper;
    @GetMapping("/truncate")
    public ResponseEntity testTruncate() {
        testMapper.truncate();
        return getResponse();
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值