????????項目中遇到了數(shù)據(jù)庫需要分庫的情況,已有功能都是按單庫實現(xiàn)的。因此升級過程中有個很重要的一項,sql查詢時要增加數(shù)據(jù)名參數(shù)。如果是sql值定義在mapper.xml中,那在接口增加一個數(shù)據(jù)庫名參數(shù)即可(工作量也不小),但是通過BaseMapper執(zhí)行的sql,沒有辦法手動增加庫名,所以必須找一個辦法既解決basemapper的問題最好也能一勞永逸。項目中用的是mybatis-plus(以下簡稱mp),我們需要在mp的生成sql動作到執(zhí)行sql動作中間將數(shù)據(jù)庫加到表名前面。mp有InnerInterceptor接口,增加庫名可以在beforePrepare方法可以實現(xiàn)。下面是具體實現(xiàn)方案。
? ? ? ? 首先自定義一個注解@SubDatabase,把所有需要分庫的表對應(yīng)的實體上都加上把需要分庫的實體都加上注解。項目啟動(實現(xiàn)CommandLineRunner)時,將注解掃出來,把實體名稱按駝峰轉(zhuǎn)下劃線改成表名,拼接一下,以備后面正則匹配用。

? ? ? ? 其次,定義一個ThreadLocal變量,再自定義個web過濾器HandlerInterceptorAdapter,在過濾器里面實現(xiàn)查詢用戶所歸屬的數(shù)據(jù)庫,并把庫名放到ThreadLocal變量中,便于后面增加庫名。這里代碼就不貼了,找地方放這個變量就行。
????????然后寫個方法,用正則表達(dá)式匹配把sql中的表名替換成帶庫名的表名,代碼如下圖所示。

? ? ? ? 可能有些同學(xué)會問為什么不直接匹配表名,要加上left join等操作匹配呢。這里主要是防止有些參數(shù)可能和表名一致,導(dǎo)致sql異常的問題。
? ? ? ? 最后自定義個InnerInterceptor,利用反射修改sql。

????????注意點,此方案適用于單數(shù)據(jù)源多數(shù)據(jù)庫場景,多數(shù)據(jù)源場景得根據(jù)具體情況調(diào)整。
????????如果各位有更好的方案,請多多指教,謝謝。