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來下來調試運行下,可以學到不少新的技巧,值得嘗試。






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM