spring動態(tài)創(chuàng)建數(shù)據(jù)源、動態(tài)切換數(shù)據(jù)源

1炭剪、創(chuàng)建動態(tài)數(shù)據(jù)源RoutingDataSource


package com.yhbc.datasourceT;

import java.util.HashMap;

import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;

import org.hibernate.SessionFactory;

import org.springframework.beans.BeansException;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Qualifier;

import org.springframework.context.ApplicationContext;

import org.springframework.context.ApplicationContextAware;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import org.springframework.stereotype.Component;

import com.alibaba.druid.pool.DruidDataSource;

//@Component? 不能有這個注解 练链,xml的bean比他晚生成

public class RoutingDataSource extends AbstractRoutingDataSource? {

private? Map dataSources = new HashMap<>();

//@Autowired

//@Qualifier("dataSource")//根據(jù)xml的id寫

private DruidDataSource defaultTargetDataSource ;//主數(shù)據(jù)源注入

JdbcTemplate jdbcTemplate;

protected SessionFactory sessionFactory;


@Override

protected DataSource determineTargetDataSource() {

// 根據(jù)數(shù)據(jù)庫選擇方案,拿到要訪問的數(shù)據(jù)庫

? ? ? ? String dataSourceName = (String) determineCurrentLookupKey();

? ? ? ? if(RoutingDataSourceContext.MASTER_DATASOURCE.equals(dataSourceName)) {

? ? ? ? ? ? // 訪問默認(rèn)主庫

? ? ? ? ? ? return defaultTargetDataSource;

? ? ? ? }


? ? ? ? // 根據(jù)數(shù)據(jù)庫名字奴拦,從已創(chuàng)建的數(shù)據(jù)庫中獲取要訪問的數(shù)據(jù)庫

? ? ? ? return (DataSource) this.dataSources.get(dataSourceName);

}

@Override

? ? protected Object determineCurrentLookupKey() {

? ? System.out.println("---determineCurrentLookupKey-----主數(shù)據(jù)源=="+defaultTargetDataSource);

? ? ? ? String dbName = RoutingDataSourceContext.getDataSourceRoutingKey();

? ? ? ? if (StringUtils.isEmpty(dbName)) {

? ? ? ? return RoutingDataSourceContext.getMainKey();

? ? ? ? }

? ? ? ? if (!dataSources.containsKey(dbName)){

? ? ? ? ? ? createAndSaveDataSource(dbName);

? ? ? ? }

? ? ? ? return dbName;

? ? }

? ? private synchronized void createAndSaveDataSource(String dbName) {

? ? ? ? DruidDataSource dataSource = createDruidDataSource(dbName);

? ? ? ? dataSources.put(dbName, dataSource);

? ? ? ? super.setTargetDataSources(dataSources);

? ? ? ? afterPropertiesSet();

? ? }





? ? /**

? ? * 根據(jù)配置創(chuàng)建DruidDataSource

? ? * @param fanDataSource

? ? * @return

? ? */

? ? public? DruidDataSource createDruidDataSource(String dbName ) {


? ? if(dataSources.containsKey(dbName)){

? ? return (DruidDataSource) dataSources.get(dbName);

? ? }

? ? ? ? DruidDataSource dataSource = new DruidDataSource();

? ? ? ? dataSource.setDriverClassName("com.mysql.jdbc.Driver");

? ? ? ? dataSource.setName(dbName);

? ? ? ? dataSource.setUrl("jdbc:mysql://192.168.1.13:3306/"+dbName+"?useUnicode=true&allowMultiQueries=true&useSSL=false");

? ? ? ? dataSource.setUsername("root");

? ? ? ? dataSource.setPassword("root");

? ? ? ? dataSource.setInitialSize(2);

? ? ? ? // 從池中取得鏈接時做健康檢查媒鼓,該做法十分保守

? ? ? ? dataSource.setTestOnBorrow(true);

? ? ? ? // 如果連接空閑超過1小時就斷開

? ? ? ? dataSource.setMinEvictableIdleTimeMillis(1 * 60000 * 60);

? ? ? ? // 每十分鐘驗(yàn)證一下連接

? ? ? ? dataSource.setTimeBetweenEvictionRunsMillis(600000);

? ? ? ? // 運(yùn)行ilde鏈接測試線程,剔除不可用的鏈接

? ? ? ? dataSource.setTestWhileIdle(true);

? ? ? ? dataSource.setMaxWait(-1);

? ? ? ? return dataSource;

? ? }


? ? /*public RoutingDataSource() {

? ? //創(chuàng)建主庫

? ? ? // createAndSaveDataSource(RoutingDataSourceContext.getMainKey());

? ? ? ? dataSources.put(RoutingDataSourceContext.MASTER_DATASOURCE,defaultTargetDataSource );

? ? ? ? System.out.println("構(gòu)造動態(tài)數(shù)據(jù)源粱坤,加入主數(shù)據(jù)源=="+defaultTargetDataSource);

? ? ? ? DruidDataSource dataSource = createDruidDataSource();

? ? ? ? jdbcTemplate = new JdbcTemplate();

? ? ? ? jdbcTemplate.setDataSource(dataSource);

? ? ? ? System.out.println("===========testQy========="+testQy());

? }*/



? ? /**

? ? * 通過jdbc從數(shù)據(jù)庫中查找數(shù)據(jù)源配置

? ? * @param name

? ? * @return

? ? */

? ? private int testQy() {

? ? ? ? String sql = "select id? from box_function? where url='1-supplyCodeList.htm' ";

? ? ? // RowMapper<FanDataSource> rowMapper = new BeanPropertyRowMapper<>(FanDataSource.class);

? ? ? ? int? id = jdbcTemplate.queryForInt(sql);

? ? ? ? return id;

? ? }



public void setDefaultTargetDataSource(DruidDataSource defaultTargetDataSource) {

System.out.println("---setDefaultTargetDataSource-----主數(shù)據(jù)源=="+defaultTargetDataSource);

this.defaultTargetDataSource = defaultTargetDataSource;

}

}

2隶糕、創(chuàng)建線程切換類RoutingDataSourceContext瓷产,用來切換數(shù)據(jù)庫的名稱

package com.yhbc.datasourceT;

public class RoutingDataSourceContext? {

? ? static final ThreadLocal<String> threadLocalDataSourceKey = new ThreadLocal<>();

? ? public static final String MASTER_DATASOURCE="defaultDataSource";

? ? /**

? ? * 獲取主數(shù)據(jù)庫的key

? ? * @return

? ? */

? ? public static String getMainKey() {

? ? ? ? return MASTER_DATASOURCE;

? ? }

? ? /**

? ? * 獲取數(shù)據(jù)庫key

? ? * @return

? ? */

? ? public static String getDataSourceRoutingKey() {

? ? ? ? String key = threadLocalDataSourceKey.get();

? ? ? ? return key == null ? getMainKey() : key;

? ? }

? ? /**

? ? * 設(shè)置數(shù)據(jù)庫的key

? ? * @param key

? ? */

? ? public static void setThreadLocalDataSourceKey(String key) {

? ? ? ? threadLocalDataSourceKey.set(key);

? ? }

}


3站玄、關(guān)鍵的一步,數(shù)據(jù)源關(guān)聯(lián)session

仔細(xì)觀察哦濒旦,routingDataSource在bean中株旷,賦予sessionFactory

<beans:bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">

<beans:property name="driverClassName" value="${silverbox.driver}" />

<beans:property name="url" value="${silverbox.url}" />

<beans:property name="username" value="${silverbox.username}" />

<beans:property name="password" value="${silverbox.password}" />

<beans:property name="maxActive" value="${silverbox.maxActive}" />

<beans:property name="validationQuery" value="${silverbox.testSql}"/>

<beans:property name="testWhileIdle" value="true"/>

<beans:property name="initialSize" value="${silverbox.initialSize}"/>

<beans:property name="maxWait" value="${silverbox.maxWait}"/>

</beans:bean>

<beans:bean id="routingDataSource" class="com.yhbc.datasourceT.RoutingDataSource">

<beans:property name="targetDataSources">

<beans:map key-type="java.lang.String">

<beans:entry key="defaultDataSource" value-ref="dataSource" />

</beans:map>

</beans:property>

<beans:property name="defaultTargetDataSource" ref="dataSource" ></beans:property>

</beans:bean>

<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

<!-- <beans:property name="dataSource" ref="dataSource" /> -->

<beans:property name="dataSource" ref="routingDataSource" />

<beans:property name="packagesToScan">

<beans:list>

<beans:value>com.yhbc.entity</beans:value>

</beans:list>

</beans:property>

<beans:property name="hibernateProperties">

<beans:value>

hibernate.dialect= org.hibernate.dialect.MySQLDialect

hibernate.show_sql=false

hibernate.format_sql=false

hibernate.query.substitutions=true 1, false 0

hibernate.jdbc.batch_size=20

hibernate.cache.use_query_cache=false

hibernate.cache.use_second_level_cache=true

hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory

hibernate.search.default.directory_provider=filesystem

hibernate.search.default.indexBase=d:\\index

</beans:value>

</beans:property>

</beans:bean>


4、測試尔邓,接下來在control中切換調(diào)用:

@RequestMapping(value = { "/hybd-findfunction.htm" }, produces = "text/html;charset=UTF-8")

? ? @ResponseBody

? ? public String findfunction(String functionUsername,String dbtype) {

? ? JSONObject jo=new JSONObject();

? ? log.info("-----------------------------/hybd-add.htm");

? ? ? ? try {

? ? ? ? //silverbox_backup

? ? ? ? /*Dbs.setDbType("backup");

? ? ? ? dynamicDataSource.determineTargetDataSource();*/

? ? ? ? if(dbtype!=null){

? ? ? ? //切換數(shù)據(jù)源晾剖,dbtype是數(shù)據(jù)庫名稱哦,這里的所有數(shù)據(jù)源默認(rèn)都是相同的host梯嗽,只是庫的區(qū)別

? ? ? ? RoutingDataSourceContext.setThreadLocalDataSourceKey(dbtype);

? ? ? ? }


? ? System.out.println("sessionFactory==="+sessionFactory.toString());


? ? ? ? List<?> list=this.hYBDService.findFunction(functionUsername);


? ? ? ? jo.put("msg", "添加成功");

? ? ? ? jo.put("list", list);

? ? ? ? jo.put("success", true);

? ? ? ? } catch (Exception e) {

? ? ? ? jo.put("success", false);

? ? ? ? ? e.printStackTrace();

? ? ? ? ? log.error("error---hybd-add.htm-----:"+Utils.log4jDetail(e));

? ? ? ? }

? ? ? ? return jo.toJSONString();

? ? }

親測通過哦齿尽,如果有用請多多支持哦

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市灯节,隨后出現(xiàn)的幾起案子循头,更是在濱河造成了極大的恐慌绵估,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卡骂,死亡現(xiàn)場離奇詭異国裳,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)全跨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門缝左,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人浓若,你說我怎么就攤上這事渺杉。” “怎么了七嫌?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵少办,是天一觀的道長。 經(jīng)常有香客問我诵原,道長英妓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任绍赛,我火速辦了婚禮蔓纠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吗蚌。我一直安慰自己腿倚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布蚯妇。 她就那樣靜靜地躺著敷燎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪箩言。 梳的紋絲不亂的頭發(fā)上硬贯,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音陨收,去河邊找鬼饭豹。 笑死,一個胖子當(dāng)著我的面吹牛务漩,可吹牛的內(nèi)容都是我干的拄衰。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼饵骨,長吁一口氣:“原來是場噩夢啊……” “哼翘悉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起居触,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤妖混,失蹤者是張志新(化名)和其女友劉穎包吝,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體源葫,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡诗越,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了息堂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嚷狞。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖荣堰,靈堂內(nèi)的尸體忽然破棺而出床未,到底是詐尸還是另有隱情,我是刑警寧澤振坚,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布薇搁,位于F島的核電站,受9級特大地震影響渡八,放射性物質(zhì)發(fā)生泄漏啃洋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一屎鳍、第九天 我趴在偏房一處隱蔽的房頂上張望宏娄。 院中可真熱鬧,春花似錦逮壁、人聲如沸孵坚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卖宠。三九已至,卻和暖如春忧饭,著一層夾襖步出監(jiān)牢的瞬間扛伍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工眷昆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蜒秤,地道東北人汁咏。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓亚斋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親攘滩。 傳聞我的和親對象是個殘疾皇子帅刊,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)漂问,斷路器赖瞒,智...
    卡卡羅2017閱讀 134,654評論 18 139
  • ?著作權(quán)歸作者所有:來自51CTO博客作者優(yōu)秀android的原創(chuàng)作品女揭,如需轉(zhuǎn)載,請注明出處栏饮,否則將追究法律責(zé)任 ...
    傳奇內(nèi)服號閱讀 1,072評論 0 9
  • 上一章:墨白淵淺|三生三世桃花依舊 2 天宮 洗梧宮裝飾著紅色的綢帶吧兔,連往日的燭臺和燈籠都換成了大紅色,夜華不喜袍嬉,...
    夏汐baby閱讀 13,623評論 4 40
  • 錯誤堆棧如下 hashMap的相關(guān)實(shí)現(xiàn)源碼如下: 顯然境蔼,工程中使用了迭代器遍歷hashMap時并且map的size...
    JeniusYang閱讀 6,282評論 0 0
  • 我是文科女生箍土,出來工作已近十年。一貫的思維習(xí)慣都是典型文科犯----委婉含蓄罐监。此前并沒覺得有什么不好吴藻,直到家人從去...
    摩登主婦閱讀 97評論 0 0