日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring集成Mybatis多数据源配置

發(fā)布時(shí)間:2025/3/11 javascript 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring集成Mybatis多数据源配置 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

既然在整理Mybatis那就把經(jīng)常用的這個(gè)多數(shù)據(jù)源的筆記也整一下吧。

Spring集成Mybatis在之前就已經(jīng)提到了。Spring集成Mybatis

集成Mybatis多數(shù)據(jù)源有兩種方式:

1、創(chuàng)建多個(gè)SqlSessionFactory,掃描每個(gè)SqlSessionFactoryBean對(duì)應(yīng)的包,形成了每個(gè)Factory對(duì)應(yīng)一個(gè)數(shù)據(jù)源。

2、創(chuàng)建一個(gè)SqlSessionFactory,通過動(dòng)態(tài)切換數(shù)據(jù)源對(duì)象,達(dá)到多數(shù)據(jù)源操作功能。

第一種方式

通過在Spring的配置文件中配置多個(gè)SqlSessionFactoryBean對(duì)象,每個(gè)對(duì)應(yīng)不同的MapperScannerConfigurer,每個(gè)MapperScannerConfigurer掃描不同的包路徑接口;

另外一個(gè)數(shù)據(jù)源也如上配置,只需替換對(duì)應(yīng)的掃描包即可,這樣調(diào)用指定包下的接口就能訪問指定的數(shù)據(jù)庫了。

第二種方式

創(chuàng)建單個(gè)SqlSessionFactory,指定默認(rèn)數(shù)據(jù)源,后期查詢不同的數(shù)據(jù)庫切換SqlSessionFactory中數(shù)據(jù)源,如果訪問次數(shù)過多,頻繁切換的話,就會(huì)導(dǎo)致一個(gè)并發(fā)問題。

解決這個(gè)問題就應(yīng)該使用并發(fā)中一些機(jī)制:如果使用鎖機(jī)制的話,那么查詢的效率就會(huì)降低,同時(shí)只有當(dāng)線程去執(zhí)行;采用ThreadLocal的話就能解決這個(gè)效率以及線程安全的問題了。

由于需切換數(shù)據(jù)源,所以在創(chuàng)建SqlSessionFactory時(shí)需要有幾個(gè)注意的點(diǎn):

1、設(shè)置數(shù)據(jù)源對(duì)象應(yīng)該為一個(gè)支持切換的一個(gè)DataSource對(duì)象,我們先定義為RouteDataSource對(duì)象,由于是DataSource所以這個(gè)RouteDataSource就必須實(shí)現(xiàn)DataSource接口,但是又不能侵入原本數(shù)據(jù)庫鏈接池的對(duì)象,所以這個(gè)采用裝飾器模式進(jìn)行裝飾這個(gè)類;

2、支持動(dòng)態(tài)切換,即需要一個(gè)暴露的靜態(tài)方法進(jìn)行切換,由于數(shù)據(jù)源對(duì)象都在這個(gè)Spring容器當(dāng)中,所以這個(gè)類需拿到Spring的容器使用權(quán)(實(shí)現(xiàn)ApplicationContextAware接口);

3、需指定切換那個(gè)數(shù)據(jù)源,可以采用ENUM枚舉進(jìn)行指定,也可以通過String,都可以。

創(chuàng)建一個(gè)枚舉類:

public enum DataSourceEnum {DATASOURCE1(null),DATASOURCE2(null);DataSource dataSource;private DataSourceEnum(DataSource dataSource) {this.dataSource = dataSource;}public DataSource getValue() {return dataSource;}public DataSourceEnum setDataSource(DataSource dataSource) {this.dataSource = dataSource;return this;}}

RouteDataSource類如下:

@Component("routeDataSource") public class RouteDataSource implements DataSource,InitializingBean,ApplicationContextAware {private static final Map<DataSourceEnum,DataSource> targetDataSources = new HashMap<DataSourceEnum,DataSource>(2); //避免并發(fā)問題ThreadLocal<DataSource> targetDataSource = new ThreadLocal<DataSource>();//裝時(shí)器模式進(jìn)行數(shù)據(jù)源增強(qiáng)private static RouteDataSource route = null;public void setDataSource(DataSource targetDataSource) {this.targetDataSource.set(targetDataSource);}@Overridepublic PrintWriter getLogWriter() throws SQLException {return targetDataSource.get().getLogWriter();}@Overridepublic void setLogWriter(PrintWriter out) throws SQLException {targetDataSource.get().setLogWriter(out);}@Overridepublic void setLoginTimeout(int seconds) throws SQLException {targetDataSource.get().setLoginTimeout(seconds);}@Overridepublic int getLoginTimeout() throws SQLException {return targetDataSource.get().getLoginTimeout();}@Overridepublic Logger getParentLogger() throws SQLFeatureNotSupportedException {return targetDataSource.get().getParentLogger();}@Overridepublic <T> T unwrap(Class<T> iface) throws SQLException {return targetDataSource.get().unwrap(iface);}@Overridepublic boolean isWrapperFor(Class<?> iface) throws SQLException {return targetDataSource.get().isWrapperFor(iface);}@Overridepublic Connection getConnection() throws SQLException {return targetDataSource.get().getConnection();}@Overridepublic Connection getConnection(String username, String password) throws SQLException {return targetDataSource.get().getConnection(username, password);}//初始化枚舉數(shù)據(jù),已經(jīng)默認(rèn)數(shù)據(jù)源@Overridepublic void afterPropertiesSet() throws Exception {targetDataSources.put(DataSourceEnum.DATASOURCE1.setDataSource((DataSource) applicationContext.getBean("dataSource")), (DataSource) applicationContext.getBean("dataSource"));targetDataSources.put(DataSourceEnum.DATASOURCE2.setDataSource((DataSource) applicationContext.getBean("dataSource1")), (DataSource) applicationContext.getBean("dataSource1"));targetDataSource.set(targetDataSources.get(DataSourceEnum.DATASOURCE1));route = (RouteDataSource) applicationContext.getBean("routeDataSource");}private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}/*** @description 更改數(shù)據(jù)源方法* @param enumDataSource*/public static void setDataSource(DataSourceEnum enumDataSource) {route.setDataSource(targetDataSources.get(enumDataSource));}}

所以在調(diào)用Mybatis的接口之前,調(diào)用RouteDataSource.setDataSource(DataSourceEnum.DATASOURCE);即可切換成對(duì)應(yīng)的數(shù)據(jù)源進(jìn)行查詢啦。

上面是一個(gè)自定義的數(shù)據(jù)源路由類,后來才發(fā)現(xiàn)在Spring的jdbc包下有個(gè)支持?jǐn)?shù)據(jù)源切換的動(dòng)態(tài)數(shù)據(jù)源類AbstractRoutingDataSource。

如果使用這個(gè)類做數(shù)據(jù)源切換,也是可以的,實(shí)現(xiàn)的思想以及模式都和自定義的那個(gè)是一致的;

示例:

public class ThreadLocalRountingDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {// TODO Auto-generated method stub//在這里做數(shù)據(jù)源切換return DataSourceTypeManager.get();}} //管理數(shù)據(jù)源類 public class DataSourceTypeManager {//數(shù)據(jù)源保存private static final ThreadLocal<MybatisDataSource> dataSourceTypes = new ThreadLocal<MybatisDataSource>() {@Overrideprotected MybatisDataSource initialValue() {return MybatisDataSource.JKDSJ;}};public static MybatisDataSource get() {return dataSourceTypes.get();}public static void set(MybatisDataSource dataSourceType) {dataSourceTypes.set(dataSourceType);}public static void reset() {dataSourceTypes.set(MybatisDataSource.JKDSJ);}}

這個(gè)類還是挺好用的

總結(jié)

以上是生活随笔為你收集整理的Spring集成Mybatis多数据源配置的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。