• Mybatis Plus注入全局操作踩坑


    起源

    最近在学习mybatis plus(下文简称mp)的进阶操作,有一个自定义全局操作。

    简单来说就是你在mapper中定义一个方法,常规的方法就是在xml文件中写具体sql或者方法上面打注解,注解里面写具体sql实现
    初次之外,mp还支持一种注入方式。这种方式类似mp提供的BaseMapper,并没有直接在xml中写sql,而是在mp启动的时候注入sql
    在实际项目使用过程中,遇到一些小问题,花费了不少时间,查阅不少资料才解决,故此记录下。
    先交代下使用的mp坐标:

    <dependency>
        <groupId>com.baomidou</groupId>
           <artifactId>mybatisplus-spring-boot-starter</artifactId>
           <version>1.0.5</version>
    </dependency>

    现场还原

    定义自己的Mapper

    public interface CustomBaseMapper<T> extends BaseMapper<T> {
        List<Integer> customCount(
            @Param("city_code") String cityCode, 
            @Param("company_code") String companyCode);
    }

    继承AutoSqlInjector

    public class CustomSqlInjector extends AutoSqlInjector {
    
        private static final String CUSTOM_COUNT = "select count(*) from %1$s where city_code = 'all' union all"
                + " select count(*) from %1$s where city_code = #{city_code} and company_code = 'all' union all"
                + " select count(*) from %1$s where city_code = #{city_code} and company_code = #{company_code}";
    
        @Override
        public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
            String sql = String.format(CUSTOM_COUNT, table.getTableName());
            String method = "customCount";
            SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
            this.addSelectMappedStatement(mapperClass, method, sqlSource, Integer.class, table);
        }
    }

    到这里我们基本写完,最后一步就是在Spring中注入CustomSqlInjector这个Bean

    @Bean
    public ISqlInjector sqlInjector() {
        return new CustomSqlInjector();
    }

    实际使用时候,如果想获得自定义方法customCount,只需要继承CustomBaseMapper即可。

    踩坑一

    项目一启动就报错,定睛一看:

    sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class异常解决方法

    这个报错有点莫名奇妙,去官网搜索一下,发现作者给了解决方案:

    MapperScan 需要排除 com.baomidou.mybatisplus.mapper.BaseMapper 类 及其 子类(自定义公共 Mapper)

    这句话当时一下子没看明白,简单浏览了下MapperScan注解,发现好像并没有排除相关的属性。后来百度了下,在一份博客下面的评论找到了答案。

    今天我也遇到类似的问题,是UserMapper文件继承了CommonMapper文件,都放在Mapper包下,然后就出现了父子Bean的问题了,将commonMapper文件从CommonMapper挪出来后,就可以了

    事后想了下应该跟官网作者说的是一个意思,只是下面这个更通俗易懂。

    踩坑二

    上面说到,需要注入自己的CustomSqlInjector。常规操作就是在标识 @Configuration的类里写上一个方法即可:

    @Bean
    public ISqlInjector sqlInjector() {
        return new CustomSqlInjector();
    }

    实际看来效果可能如下,但这样启动发现自定义操作并没有注入进去。经过一番摸索,去翻阅了官网2.x的文档,跳转到自定义全局操作 一节。
    当时文档上写的注入方式是用配置文件完成:

    <!-- 定义 MP 全局策略,安装集成文档部分结合 -->
    <bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
        .....
    
      <!-- 自定义注入 deleteAll 方法  -->
      <property name="sqlInjector" ref="mySqlInjector" />
    </bean>
    
    <!-- 自定义注入器 -->
    <bean id="mySqlInjector" class="com.baomidou.test.MySqlInjector" />

    定睛一看,写在GlobalConfiguration这个标签下,于是我想到是否可以尝试在application.yml文件进行同样的配置:

    mybatis-plus:
      mapper-locations:
        - classpath*:mapper/*.xml
      typeAliasesPackage: com.test.tao.*.model.domain
      global-config:
        id-type: 0
        field-strategy: 2
        db-column-underline: true
        sql-injector: com.test.tao.operation.inject.CustomSqlInjector
      configuration:
        map-underscore-to-camel-case: true
        cache-enabled: false

    经过这样一配置,发现成功了,注入成功了。

    虽然解决方案很简单,但那天晚上缺尝试了很久。

    后来我看了mp官方给的示例,注入方式改变了,简化了很多。其实把mp官方给的demo来下来调试运行下,可以学到不少新的技巧,值得尝试。





    网络知识搬运/梳理小工
  • 相关阅读:
    GeoHash
    CMake官方教程翻译文档
    常用开源系统
    Python Tools
    CMake 笔记
    Nginx 多进程连接请求/事件分发流程分析
    连麦方案中各条流之间时间戳同步问题
    音视频重新编码时间戳同步问题
    基于网络流音视频包的音视频解码思路
    协程库st(state threads library)原理解析
  • 原文地址:https://www.cnblogs.com/aibilim/p/ac6e69bfe4f90a50551d35ff68e884b7.html
Copyright © 2020-2023  润新知