Java教程

MyBatisPlus自定义全局SQL注入器

本文主要是介绍MyBatisPlus自定义全局SQL注入器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、ISqlInjector自动注入器接口

通过实现MyBatisPlus的ISqlInjector接口可以自定义各种sql,注入到全局中,相当于自定义的MyBatisPlus自动注入的方法。之前需要在xml中进行配置的sql语句,现在通过扩展ISqlInjector接口在加载MyBatis环境时就注入。

DefaultSqlInjector是默认SQL注入器,它继承了AbstractSqlInjector,如果想要扩展SQL注入器,可以通过继承DefaultSqlInjector来实现

/**
 * SQL 默认注入器
 *
 * @author hubin
 * @since 2018-04-10
 */
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());
    }
}

AbstractSqlInjector类实现了ISqlInjector接口

/**
 * SQL 自动注入器
 *
 * @author hubin
 * @since 2018-04-07
 */
public abstract class AbstractSqlInjector implements ISqlInjector {

    private static final Log logger = LogFactory.getLog(AbstractSqlInjector.class);

    @Override
    public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
        Class<?> modelClass = extractModelClass(mapperClass);
        if (modelClass != null) {
            String className = mapperClass.toString();
            Set<String> mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration());
            if (!mapperRegistryCache.contains(className)) {
                List<AbstractMethod> methodList = this.getMethodList(mapperClass);
                if (CollectionUtils.isNotEmpty(methodList)) {
                    TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
                    // 循环注入自定义方法
                    methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));
                } else {
                    logger.debug(mapperClass.toString() + ", No effective injection method was found.");
                }
                mapperRegistryCache.add(className);
            }
        }
    }

    /**
     * <p>
     * 获取 注入的方法
     * </p>
     *
     * @param mapperClass 当前mapper
     * @return 注入的方法集合
     * @since 3.1.2 add  mapperClass
     */
    public abstract List<AbstractMethod> getMethodList(Class<?> mapperClass);

    /**
     * 提取泛型模型,多泛型的时候请将泛型T放在第一位
     *
     * @param mapperClass mapper 接口
     * @return mapper 泛型
     */
    protected Class<?> extractModelClass(Class<?> mapperClass) {
        Type[] types = mapperClass.getGenericInterfaces();
        ParameterizedType target = null;
        for (Type type : types) {
            if (type instanceof ParameterizedType) {
                Type[] typeArray = ((ParameterizedType) type).getActualTypeArguments();
                if (ArrayUtils.isNotEmpty(typeArray)) {
                    for (Type t : typeArray) {
                        if (t instanceof TypeVariable || t instanceof WildcardType) {
                            break;
                        } else {
                            target = (ParameterizedType) type;
                            break;
                        }
                    }
                }
                break;
            }
        }
        return target == null ? null : (Class<?>) target.getActualTypeArguments()[0];
    }
}

二、自定义SQL注入器

创建一个类,将方法和sql做映射

public class MysqlDeleteAll extends AbstractMethod{
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        String sql = "delete from " + tableInfo.getTableName();
        String methodName = "deleteAll";

        // 进行预编译得到sqlSource对象
        SqlSource sqlSource = languageDriver.createSqlSource(configuration,sql,modelClass);

        //添加到delete操作的Statement中也就是相当于将预编译sql和其它的delete相关的编译后的sql存在一起
        //将EmployeeMapper中定义的deleteAll处理成对应的MapperedStatement对象,加入到configuration对象中
        return addDeleteMappedStatement(mapperClass, methodName,sqlSource);
    }
}

创建自定义的注入器,继承DefaultSqlInjector,将sql与方法绑定的实例交给Spring来管理

/**
 * 自定义SQL注入器
 */
public class MySqlInjector extends DefaultSqlInjector{

    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        /* 如果只需增加方法,保留MP自带方法
         * 可以super.getMethodList() 再add
         *
         * */
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        methodList.add(new MysqlDeleteAll());

        return methodList;
    }
}

将自定义方法名添加到继承了BaseMapperEmployeeMapper

/**
 * <p>
 *  Mapper 接口
 * </p>
 *
 * @author Jian
 * @since 2021-05-21
 */
public interface EmployeeMapper extends BaseMapper<Employee> {

    public int deleteAll();

}

将自定义注入器注册到Spring容器中,并且将自定义的SQL注入器注册到全局策略配置

    <!--定义MyBatisPlus全局策略配置-->
    <bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
        <property name="dbConfig">
            <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
                <!--实现属性名与数据库表的列名的映射-->
                <property name="tableUnderline" value="true"></property>
                <!--全局的主键策略-->
                <property name="idType" value="AUTO"></property>
                <!--全局的表前缀策略配置-->
                <property name="tablePrefix" value="tbl_"></property>

            </bean>

        </property>

        <!--将自定义的SQL注入器注册到全局-->
        <property name="sqlInjector" ref="mySqlInjector"></property>

    </bean>

    <!--定义自定义的注入器bean-->
    <bean id="mySqlInjector" class="mpGenerator.injector.MySqlInjector"></bean>

测试自定义注入器的deleteAll方法

    @Test
    public void testDeleteAll(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        EmployeeMapper employeeMapper = context.getBean("employeeMapper",EmployeeMapper.class);

        int result = employeeMapper.deleteAll();

        System.out.println("result: " + result);
    }

打印日志:
在这里插入图片描述

这篇关于MyBatisPlus自定义全局SQL注入器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!