SpringCloud集成 Mybatis分表插件shardbatis 踩坑日誌及其原理分析

公司新開發的系統數據量過大,須要進行分表處理,我在網上瀏覽一圈,選中了Shardbatis,緣由有二:sql

1.公司項目自己集成了Mybatis,而Shardbatis是其插件,引入方便;數據庫

2.Sharbatis十分輕便,只要稍微配置一下便可使用;數組

如何引入,百度一大堆,這裏再也不贅述,下面分析一下其原理:mybatis

Shardbatis說白了就是一個interceptor(攔截器),它的原理跟Mybatis的分頁插件(PageHelper)差很少,PageHelper其實也是依賴interceptor(攔截器)進行攔截將要發送到數據庫執行的sql,作進一步處理的插件。app

研究源碼能夠看到,PageHelper實現了Interceptor(攔截器)接口:this

@Intercepts({@Signature(
    type = Executor.class,
    method = "query",
    args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}
)})
public class PageHelper implements Interceptor {
    private SqlUtil sqlUtil;
    private Properties properties;
    private SqlUtilConfig sqlUtilConfig;
    private boolean autoDialect = true;
    private boolean autoRuntimeDialect;
    private boolean closeConn = true;
    private Map<String, SqlUtil> urlSqlUtilMap = new ConcurrentHashMap();

    public PageHelper() {
    }
...省略

Shardbatis也實現了Interceptor(攔截器)接口:google

@Intercepts({@Signature(
        type = StatementHandler.class,
        method = "prepare",
        args = {Connection.class}
)})
public class ShardPlugin implements Interceptor {
    private static final Log log = LogFactory.getLog(com.google.code.shardbatis.plugin.ShardPlugin.class);
    public static final String SHARDING_CONFIG = "shardingConfig";
    private static final ConcurrentHashMap<String, Boolean> cache = new ConcurrentHashMap();

    public ShardPlugin() {
    }
...省略

咱們在初始化SqlSessionFactory的時候,能夠配置對應的攔截器,代碼以下:url

@Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
        SqlSessionFactoryBean bean = MybatisKit.newMybatisSessionFactory(dataSource, this.mybatisProperties);
        //初始化分表插件
        ShardPlugin shardPlugin = new ShardPlugin();
        //..省略
        
        //初始化分頁插件
        PageHelper pageHelper = new PageHelper();
        //..省略 
        

        //根據本身須要攔截的順序,組裝數組
        Interceptor[] plugins = new Interceptor[]{shardPlugin,pageHelper};
        //將插件引入SqlSessionFactory
        bean.setPlugins(plugins);
        return bean;
    }

這樣,就能夠攔截Mybatis即將執行的Sql作進一步處理。插件

接下來,來分享一下,我集成Shardbatis時踩到的坑:3d

我依賴的是Shardbatis版本以下:

<dependency>
    <groupId>org.shardbatis</groupId>
    <artifactId>shardbatis</artifactId>
    <version>2.0.0B</version>
</dependency>

當運行的時候報了以下錯誤:

這個錯誤讓我重複檢查了代碼N次,以及調試了N次仍然沒找到錯誤。在網上瘋狂百度搜索,最後在官網issue看到這個:

而後我翻一下我集成的ShardBatis插件源碼,發現:

這確實夠坑的,沒辦法,使用開源的東西,就得踩它的坑。最後,我重寫了ShardPlugin類,加上Integer.class ,完美解決問題:以下:

@Intercepts({@Signature(
        type = StatementHandler.class,
        method = "prepare",
        args = {Connection.class,Integer.class}
)})
public class ShardPlugin implements Interceptor {
    private static final Log log = LogFactory.getLog(com.google.code.shardbatis.plugin.ShardPlugin.class);
    public static final String SHARDING_CONFIG = "shardingConfig";
    private static final ConcurrentHashMap<String, Boolean> cache = new ConcurrentHashMap();

    public ShardPlugin() {
    }
...省略

好了,本博客分享到此結束,謝謝。

相關文章
相關標籤/搜索