當前位置:首頁 » 操作系統 » spring多資料庫

spring多資料庫

發布時間: 2022-12-22 02:48:27

⑴ springboot、mybatis-plus、Druid多數據源環境搭建

java單體項目里,我們一般是只需配置一個資料庫,這時代碼里的層都是只對一個資料庫操作;但有時候我們的數據可能在2個或者3個資料庫,這時就需要配置更多數據源,進行資料庫直連操作,下面以Mysql的兩個庫為例(Oracle也就換個驅動類與連接串)。

(本文閱讀大概花費兩分鍾)

技術條件:

springboot 2.5.3 (即springframework 5.3.9)

MySQL 5.7

mybatis-plus 3.5.0

dynamic-datasource 3.5.0

druid 1.2.9

idea開發工具、maven 3.3.9

1、導入相關依賴

2、建立兩個資料庫mydb(表 user)、db2(表t_class),並分別建一張表

3、編寫application.yaml配置文件

4、編寫po類、層、一個介面測試類

其中,在的類加上對應的數據源標識符,使用此註解com.baomidou.dynamic.datasource.annotation.DS

5、啟動項目,查看結果

至此,多數據源環境集成成功;當然這里只使用了查詢功能,對應事務相關的下一回合文章再做討論啥。

⑵ SpringBoot+Mybatis 通過databaseIdProvider支持多資料庫

本人最近接到一個任務,將一個系統改成同時兼容Oracle和PostgreSQL(原來是僅支持Oracle)。雖然大部分的sql語句通用,但是還有許多語法存在差異,所以我們可以通過mybatis自身提供的databaseIdProvider解決這個問題,這里記錄一下過程。

通過配置文件開啟mysql支持或者postgresql支持

⑶ Spring Boot(十二):MyBatis-Plus的多數據源和分頁

同一個項目有時會涉及到多個資料庫,這時我們就要配置多個數據源。配置多數據源的常見情況有以下兩種:

1)同一個項目中涉及兩個或多個業務資料庫,它們之間相互獨立,這種情況也可以作為兩個或多個項目來開發

2)兩個或多個資料庫之間是主從關系,主庫負責寫,從庫負責讀

1、pom.xml配置

在pom.xml中增加MyBatis-Plus多數據源依賴:

2、配置文件配置

在配置文件application.yml中配置我們需要連接的資料庫:blog和user,默認為blog

3、啟動類配置

在@SpringBootApplication註解上增加exclude = DruidDataSourceAutoConfigure.class配置:

這個配置的作用是去掉對DruidDataSourceAutoConfigure的自動配置,否則程序會報錯:

原因:

DruidDataSourceAutoConfigure在之前,其會注入一個DataSourceWrapper,會在原生的spring.datasource下找url, username, password等,而我們動態數據源的配置路徑是變化的。

4、實體類和層配置

在po文件夾下創建blog和user文件夾,分別用於存儲blog資料庫和user資料庫的實體:

註解:

@TableName: 表名註解,標識實體類對應的表

@TableId: 主鍵註解,當type = IdType.AUTO時,表示這個主鍵是自增主鍵

在文件夾下創建blog和user文件夾,分別用於存儲blog和user的:

註解:

@Repository: 將數據訪問層(DAO層)的類標識為Spring Bean

@DS: 配置非默認數據源,本示例中blog為默認數據源,user為非默認數據源,在使用@DS註解時,有如下注意事項:

1)不能使用事務,否則數據源不會切換,使用的還是第一次載入的數據源

2)第一次載入數據源之後,第二次,第三次……操作其他數據源,如果數據源不存在,使用的還是第一次載入的數據源

3)數據源名稱不要包含下劃線,否則不能切換

5、測試驗證

編寫ArticleController和UserInfoController:

注 : 業務邏輯復雜時,Controller和Mapper中間會有Service層來處理業務邏輯,現在我們就簡單的測試一下多數據源,所以直接使用Controller調用Mapper了

1、配置分頁插件

2、分頁方法

1)使用MyBatis-Plus的selectPage方法

使用MyBatis-Plus的selectPage方法,返回了IPage,示例:

2)sql分頁

有時候有些分頁需要關聯多張表,使用LambdaQueryWrapper不太方便,這時候可以自己寫sql來實現分頁,主要有兩種:純sql自己實現分頁和使用IPage實現分頁

注 : 這里的sql示例就使用單表查詢了,具體的可根據業務場景使用多表查詢

A、純sql自己實現分頁

分頁的數據list和總條數單獨調用方法返回 :

B、使用IPage實現分頁(常用)

返回IPage,返回值的數據結構見「 1)使用MyBatis-Plus的selectPage方法

本文簡單介紹了一下MyBatis-Plus的多數據源和分頁,本文示例代碼, 詳見https://gitee.com/tunan222/spring-boot-demo

若您覺得還可以,請幫忙點個 「贊」 ,謝謝

⑷ spring+mybatis 多資料庫事務管理:一個方法裡面能同時對兩個資料庫的數據進行操作

  1. 定義兩個DAO分別使用不同的數據源,ADAO連接A資料庫,BDAO連接B資料庫

  2. 定義一個Service類,加上Spring註解@Transactional,表示進行事務管理。

    將ADAO和BDAO注入到Service類裡面。

    在service類裡面創建一個方法,方法里調用ADAO的方法插入數據到A資料庫的user表,然後調用BDAO的方法插入數據到B資料庫的user表

⑸ Spring怎樣高效的配置多套數據源

1、首先配置多個datasource

<!-- 主資料庫的數據據源 -->
<bean id="masterDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@192.168.10.11:1521:trew" />
<property name="username" value="poi" />
<property name="password" value="poi" />
</bean>
<!-- 備份庫的數據據源 -->
<bean id="slaveDataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@192.168.10.12:1521:trew" />
<property name="username" value="poi2" />
<property name="password" value="poi2" />
</bean>

2、寫一個DynamicDataSource類繼承AbstractRoutingDataSource,並實現determineCurrentLookupKey方法

?
public class DynamicDataSource extends AbstractRoutingDataSource {
@SuppressWarnings("unused")
private Log logger = LogFactory.getLog(getClass());

@Override
protected Object determineCurrentLookupKey() {
return DbContextHolder.getDbType();
}
}

public class DbContextHolder {
@SuppressWarnings("rawtypes")

private static final ThreadLocal contextHolder = new ThreadLocal();

@SuppressWarnings("unchecked")
public static void setDbType(String dbType) {
contextHolder.set(dbType);
}

public static String getDbType() {
return (String) contextHolder.get();
}

public static void clearDbType() {
contextHolder.remove();
}
}

3. 配置動態數據源

<!--將DynamicDataSource Bean加入到Spring的上下文xml配置文件中去,同時配置DynamicDataSource的targetDataSources(多數據源目標)屬性的Map映射。-->

<bean id="dataSource" class="cn.com.core.datasource.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="masterDataSource" value-ref="masterDataSource" />
<entry key="slaveDataSource" value-ref="slaveDataSource" />
</map>
</property>
<property name="defaultTargetDataSource" ref="masterDataSource"/>
</bean>

4.使用動態數據源(hibernate)

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="lobHandler" ref="lobHandler"/>
<property name="eventListeners">
<map>
<entry key="post-insert">
<ref bean="logListener"/>
</entry>
<entry key="post-update">
<ref bean="logListener"/>
</entry>
<entry key="post-delete">
<ref bean="logListener"/>
</entry>
</map>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.Oracle10gDialect
<!-- org.hibernate.dialect.OracleDerbyDialect -->
</prop>
<prop key="hibernate.show_sql">true</prop>
<!-- <prop key="hibernate.generate_statistics">true</prop> -->
<prop key="hibernate.connection.release_mode">
auto
</prop>
<prop key="hibernate.autoReconnect">true</prop>
<!--
<prop key="hibernate.hbm2ddl.auto">update</prop>
-->
<prop key="hibernate.cache.use_second_level_cache">false</prop>
<prop key="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</prop>
<prop key="hibernate.cache.use_query_cache">false</prop>

</props>
</property>
</bean>

使用Hibernate時的事務管理配置示例:

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
< property name="sessionFactory" ref="sessionFactory" />
bean>

⑹ Spring中如何配置多個資料庫連接

1.解決方案:
property name="<.commons; value=" value="close".properties文件
2.配置多個資料庫:
jdbc;minEvictableIdleTimeMillis"driverClassName".maxActive}" /
password}".url}"${jdbc;>.driver;3600000"maxActive";>${jdbc.driver}"
/username"${dbcp;
</ value=".dbcp;url".BasicDataSource"
< value="bean id=".username}"
< value="
<>password"${dbcp;org.;dataSource"false" /
<property name=" destroy-method="3600000"
application;property name=" class=",property name="
< value=">.apache; value=" /property name=">
<${jdbc;property name="property name=">.;

⑺ 15《Spring Boot 入門教程》多數據源與分布式事務

一個項目中使用多個數據源的需求,我們在日常工作中時常會遇到。

以商城系統為例,有一個 MySQL 的資料庫負責存儲交易數據。公司還有一套 ERP 企業信息化管理系統,要求訂單信息同步錄入 ERP 資料庫,便於公司統一管理,而該 ERP 系統採用的資料庫為 SQL Server 。

此時,就可以在 Spring Boot 項目中配置多個數據源。另外,使用多數據源後,需要採用分布式事務來保持數據的完整性。

本小節我們使用 Spring Boot 開發一個商城系統的訂單生成功能,訂單信息同時進入 MySQL 與 SQL Server 資料庫。

首先創建 MySQL 資料庫 shop ,並新建訂單表 order ,表結構如下:


order 表結構

然後創建 SQL Server 資料庫 erpshop ,並新建訂單表 erp_order ,表結構如下。注意 id 是自增長的唯一標識,out_id 是對應訂單在 MySQL 資料庫中的唯一標識,以便在兩個庫中比對訂單。

erp_order 結構

接下來,我們開始實現 Spring Boot 後端項目,數據持久層採用 MyBatis 框架,同時訪問兩個數據源。

Spring Boot 版本選擇 2.2.5 ,Group 為 com.imooc , Artifact 為 spring-boot-multidb,生成項目後導入 Eclipse 開發環境。

我們引入熱部署依賴、 Web 依賴、資料庫訪問相關依賴及測試相關依賴,具體如下:

實例:

由於我們要同時訪問兩個資料庫,所以需要在配置文件中添加兩個數據源的配置信息。注意配置多數據源時, url 配置需要使用 spring.datasource.db1.jdbc-url=xxx 的形式。

實例:

多個數據源的情況下, 我們需要通過配置類,將數據源注冊為組件放入 Spring 容器中。

實例:

通過這個配置類, Spring 容器中就有兩個數據源組件,這兩個組件分別採用 spring.datasource.db1 和 spring.datasource.db2 開頭的配置信息。所以通過這兩個組件,就能分別操作 MySQL 數據源 1 和 SQL Sever 數據源 2 。

多數據源情況下, MyBatis 中的關鍵組件 SqlSessionFactory 和 SqlSessionTemplate 也需要單獨配置,我們需要為兩個數據源分別配置一套組件。

實例:

通過上面的配置類, com.imooc.springbootmultidb.mapper1 包中的 DAO 數據訪問介面會自動調用 sqlSessionTemplate1 組件實現具體資料庫操作,而 sqlSessionTemplate1 操作的數據源已經通過配置類設置為 db1 。同時, DAO 數據訪問介面對應的映射文件已經指定到 classpath:mapper1/ 目錄去尋找。這樣數據源 – DAO 數據訪問介面 – 映射文件三者的對應關系就建立起來了。

數據源 2 的配置方法是一樣的, com.imooc.springbootmultidb.mapper2 包中的 DAO 數據訪問介面會自動調用 sqlSessionTemplate2 組件,其操作的數據源即為 db2 ,其對應的映射文件指定到 classpath:mapper2/ 目錄去尋找。

實例:

數據訪問介面的位置已經在配置類指定,首先在 com.imooc.springbootmultidb.mapper1 創建 OrderDao ,操作的是數據源 1 中的 order 表。

實例:

然後在 com.imooc.springbootmultidb.mapper2 創建 ErpOrderDao ,操作的是數據源 2 中的 erporder 表。

實例:

這兩個介面中使用的數據對象比較簡單,代碼如下:

實例:

分別針對 OrderDao 、 ErpOrderDao 編寫對應的映射文件,然後按照配置類指定的位置,兩個文件分別放到 resources/mapper1 和 resources/mapper2 目錄下。

實例:

實例:

數據操作介面與對應的映射文件均已編寫完畢,現在可以通過測試類進行多數據源測試了,我們在測試類中同時向兩個庫插入記錄。

實例:

運行測試方法後,兩個資料庫表中均新增數據成功,這樣我們就成功的使用 Spring Boot 同時操作了兩個數據源。

採用多數據源之後,事務的實現方式也隨之發生變化。當某個數據源操作出現異常時,該數據源和其他數據源的事務都需要回滾。這種涉及多個數據源的事務,稱為分布式事務,接來下我們就來具體實現一下。

在 pom.xml 引入 Atomikos 事務管理器相關的依賴項, Atomikos 是一個開源的事務管理器,支持分布式事務。

實例:

需要將默認的數據源更換為支持分布式事務的數據源, MySQL 對應的數據源為 MysqlXADataSource , SQL Server 對應的數據源為 SQLServerXADataSource 。

實例:

繼續修改 DataSourceConfig 類,在其中配置分布式事務管理器組件。當項目中使用事務時,會通過配置的分布式事務管理器管理分布式事務操作。

實例:

在測試方法上添加 @Transactional 開啟事務,然後在兩個數據源操作中間模擬拋出異常。

實例:

此時運行測試類,可以發現數據源 1 的事務已回滾,驗證成功!

在開發 Spring Boot 項目時,如果默認配置滿足不了我們的需求,可以通過手工配置組件實現我們需要的功能。這些組件可能是各個公司提供的,我們根據相應文檔,為其配置各個屬性即可。

⑻ spring boot怎麼連接多種資料庫

新建Spring Boot項目,依賴選擇JPA(spring-boot-starter-data-jpa)和Web(spring-bootstarter-web)。

配置基本屬性 在application.properties里配置數據源和jpa的相關屬性
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springboot
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jackson.serialization.indent_output=true

定義映射實體類

定義Controller類
@RestControllerpublic class PersonCtroller {
@Autowired PersonServer personServer;
@RequestMapping("/rollback")
public Person rollback(Person person){
return personServer.savePersonWithRollBack(person);
}
@RequestMapping("/norollback")
public Person noRollback(Person person){
return personServer.savePersonWithOutRollBack(person);
}
}
定義數據訪問層
public interface PersonRepository extends JpaRepository<Person, Long> {}
定義Server層
@Servicepublic class PersonServerImp implements PersonServer {
@Autowired
PersonRepository personRepository;
@Transactional(rollbackFor = {IllegalArgumentException.class})
@Override
public Person savePersonWithRollBack(Person person) {
Person p = personRepository.save(person);
if (p.getName().equals("xxx")){
throw new IllegalArgumentException("用戶已存在,數據會回滾");
}
return p;
}
}
7
瀏覽器訪問

⑼ 如何在spring框架中解決多數據源的問題

在 我們的項目中遇到這樣一個問題:我們的項目需要連接多個資料庫,而且不同的客戶在每次訪問中根據需要會去訪問不同的資料庫。我們以往 在 spring 和 hibernate 框架中總是配置一個數據源,因而 sessionFactory 的dataSource 屬性總是指向這個 數據源並且恆定不變,所有 DAO 在使用 sessionFactory 的時候都是通過這個數據源訪問資料庫。但是現在,由於項目的需要,我們 的 DAO 在訪問 sessionFactory 的時候都不得不在多個數據源中不斷切換,問題就出現了:如何讓 sessionFactory 在執 行數據持久化的時候,根據客戶的需求能夠動態切換不同的數據源?我們能不能在 spring 的框架下通過少量修改得到解決?是否有什麼設計模式可以利用 呢?
問題的分析
我 首先想到在 spring 的 applicationContext 中配置所有的 dataSource 。這些 dataSource 可能是各種 不同類型的,比如不同的資料庫: Oracle 、 SQL Server 、 MySQL 等,也可能是不同的數據源:比如 apache 提供的 org.apache.commons.dbcp.BasicDataSource 、 spring 提供的 org.springframework.jndi.JndiObjectFactoryBean 等。然後 sessionFactory 根據客戶的 每次請求,將dataSource 屬性設置成不同的數據源,以到達切換數據源的目的。
但 是,我很快發現一個問題:當多用戶同時並發訪問資料庫的時候會出現資源爭用的問題。這都是「單例模式」惹的禍。眾所周知,我們在使用 spring 框架 的時候,在 beanFactory 中注冊的 bean 基本上都是採用單例模式,即 spring 在啟動的時候,這些 bean 就裝載到內存中, 並且每個 bean 在整個項目中只存在一個對象。正因為只存在一個對象,對象的所有屬性,更准確說是實例變數,表現得就如同是個靜態變數(實際上「靜 態」與「單例」往往是非常相似的兩個東西,我們常常用「靜態」來實現「單例」)。拿我們的問題來說, sessionFactory 在整個項目中只有一 個對象,它的實例變數 dataSource 也就只有一個,就如同一個靜態變數一般。如果不同的用戶都不斷地去修改 dataSource 的值,必然 會出現多用戶爭用一個變數的問題,對系統產生隱患。
通過以上的分析,解決多數據源訪問問題的關鍵,就集中在 sessionFactory 在執行數據持久化的時候,能夠通過某段代碼去根據客戶的需要動態切換數據源,並解決資源爭用的問題。
問題的解決
(一) 採用 Decorator 設計模式
要 解決這個問題,我的思路鎖定在了這個 dataSource 上了。如果 sessionFactory 指向的 dataSource 可以根據客戶的 需求去連接客戶所需要的真正的數據源,即提供動態切換數據源的功能,那麼問題就解決了。那麼我們怎麼做呢?去修改那些我們要使用 的 dataSource 源碼嗎?這顯然不是一個好的方案,我們希望我們的修改與原dataSource 代碼是分離的。根據以上的分析,使 用 GoF 設計模式中的 Decorator 模式(裝飾者模式)應當是我們可以選擇的最佳方案。
什 么是「 Decorator 模式」?簡單點兒說就是當我們需要修改原有的功能,但我們又不願直接去修改原有的代碼時,設計一個 Decorator 套 在原有代碼外面。當我們使用 Decorator 的時候與原類完全一樣,當 Decorator 的某些功能卻已經修改為了我們需要修改的功 能。 Decorator 模式的結構如圖。

我 們本來需要修改圖中所有具體的 Component 類的一些功能,但卻並不是去直接修改它們的代碼,而是在它們的外面增加一 個 Decorator 。 Decorator 與具體的 Component 類都是繼承的 AbstractComponent ,因此它長得和具 體的 Component 類一樣,也就是說我們在使用 Decorator 的時候就如同在使用 ConcreteComponentA 或者 ConcreteComponentB 一樣,甚至那些使用 ConcreteComponentA 或者 ConcreteComponentB 的客 戶程序都不知道它們用的類已經改為了 Decorator ,但是 Decorator 已經對具體的 Component 類的部分方法進行了修改,執 行這些方法的結果已經不同了。
(二) 設計 MultiDataSource 類
現 在回到我們的問題,我們需要對 dataSource 的功能進行變更,但又不希望修改 dataSource 中的任何代碼。我這里指 的 dataSource 是所有實現 javax.sql.DataSource 介面的類,我們常用的包括 apache 提供的 org.apache.commons.dbcp.BasicDataSource 、 spring 提供的 org.springframework.jndi.JndiObjectFactoryBean 等,這些類我們不可能修改它們本身,更不可能對它們一 個個地修改以實現動態分配數據源的功能,同時,我們又希望使用 dataSource 的 sessionFactory 根本就感覺不到這樣的變 化。 Decorator 模式就正是解決這個問題的設計模式。
首先寫一個 Decorator 類,我取名叫 MultiDataSource,通過它來動態切換數據源 。同時在配置文件中將sessionFactory的dataSource屬性由原來的某個具體的dataSource改為MultiDataSource。如圖:

對 比原Decorator 模式, AbstractComponent 是一個抽象類,但在這里我們可以將這個抽象類用介面來代替,即 DataSource 介面,而 ConcreteComponent 就是那些 DataSource 的實現類, 如 BasicDataSource 、JndiObjectFactoryBean 等。 MultiDataSource 封裝了具體的 dataSource,並實現了數據源動態切換:

java 代碼

public class MultiDataSource implements DataSource {
private DataSource dataSource = null ;
public MultiDataSource(DataSource dataSource){
this .dataSource = dataSource;
}

public Connection getConnection() throws SQLException {
return getDataSource().getConnection();
}
//其它DataSource介面應當實現的方法

public DataSource getDataSource(){
return this .dataSource;
}
}
public void setDataSource(DataSource dataSource) {
this .dataSource = dataSource;
}
}
客 戶在發出請求的時候,將dataSourceName放到request中,然後把request中的數據源名通過調用 newMultiDataSource(dataSource) 時可以告訴 MultiDataSource 客戶需要的數據源,就可以實現動態切換數 據源了。但細心的朋友會發現這在單例的情況下就是問題的,因為 MultiDataSource 在系統中只有一個對象,它的實例變 量 dataSource 也只有一個,就如同一個靜態變數一般。正因為如此, 單例模式讓許多設計模式都不得不需要更改,這將在我的《「單例」更改了我 們的設計模式》中詳細討論。那麼,我們在單例模式下如何設計呢?
(三) 單例模式下的 MultiDataSource
在 單例模式下,由於我們在每次調用 MultiDataSource 的方法的時候, dataSource 都可能是不同的,所以我們不能 將 dataSource 放在實例變數 dataSource 中,最簡單的方式就是在方法 getDataSource() 中增加參數,告 訴 MultiDataSource 我到底調用的是哪個 dataSource :
java 代碼
public DataSource getDataSource(String dataSourceName){
log.debug( "dataSourceName:" +dataSourceName);
try {
if (dataSourceName== null ||dataSourceName.equals( "" )){
return this .dataSource;
}
return (DataSource) this .applicationContext.getBean(dataSourceName);
} catch (NoSuchBeanDefinitionException ex){
throw new DaoException( "There is not the dataSource
}
}
值得一提的是,我需要的數據源已經都在spring 的配置文件中注冊, dataSourceName 就是其對應的 id 。
xml 代碼
< bean id = "dataSource1"
class = "org.apache.commons.dbcp.BasicDataSource" >
< property name = "driverClassName" >
< value > oracle.jdbc.driver.OracleDriver value >
property >
......
bean >
< bean id = "dataSource2"
class = "org.apache.commons.dbcp.BasicDataSource" >
< property name = "driverClassName" >
< value > oracle.jdbc.driver.OracleDriver value >
property >
......
bean >
為了得到spring 的 ApplicationContext , MultiDataSource 類必須實現介面org.springframework.context.ApplicationContextAware ,並且實現方法:
java 代碼
private ApplicationContext applicationContext = null ;
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this .applicationContext = applicationContext;
}
如此這樣,我就可以通過this . applicationContext .getBean(dataSourceName) 得到 dataSource 了。
(四) 通過線程傳遞 dataSourceName
查 看以上設計, MultiDataSource 依然無法運行,因為用戶在發出請求時,他需要連接什麼資料庫,其數據源名是放在 request 中的, 要將 request 中的數據源名傳給 MultiDataSource ,需要經過 BUS 和 DAO ,也就是說為了把數據源名傳 給 MultiDataSource , BUS 和 DAO 的所有方法都要增加 dataSourceName 的參數,這是我們不願看到的。寫一個 類,通過線程的方式跳過 BUS 和 DAO 直接傳遞給 MultiDataSource 是一個不錯的設計:

java 代碼
public class SpObserver {
private static ThreadLocal local = new ThreadLocal();
public static void putSp(String sp) {
local.set(sp);
}
public static String getSp() {
return (String)local.get();
}
}
做一個filter ,每次客戶發出請求的時候就調用 SpObserver.petSp ( dataSourceName ) ,將 request 中的dataSourceName 傳遞給 SpObserver 對象。 最後修改 MultiDataSource 的方法 getDataSource() :
java 代碼
public DataSource getDataSource(){
String sp = SpObserver.getSp();
return getDataSource(sp);
}
完整的MultiDataSource 代碼在附件中。
(五) 動態添加數據源
通 過以上方案,我們解決了動態分配數據源的問題,但你可能提出疑問:方案中的數據源都是配置在 spring 的 ApplicationContext 中,如果我在程序運行過程中動態添加數據源怎麼辦?這確實是一個問題,而且在我們的項目中也確實遇 到。 spring 的 ApplicationContext 是在項目啟動的時候載入的。載入以後,我們如何動態地載入新的 bean 到 ApplicationContext 中呢?我想到如果用 spring 自己的方法解決這個問題就好了。所幸的是,在查看 spring 的源代碼後,我找到了這樣的代碼,編寫了 DynamicLoadBean 類,只要 調用loadBean() 方法,就可以將某個或某 幾個配置文件中的 bean 載入到 ApplicationContext 中(見附件)。不通過配置文件直接載入對象,在spring 的源碼中也 有,感興趣的朋友可以自己研究。
(六) 在 spring 中配置
在完成了所有這些設計以後,我最後再嘮叨一句。我們應當在 spring 中做如下配置:
xml 代碼
< bean id = "dynamicLoadBean" class = "com.htxx.service..DynamicLoadBean" > bean >
< bean id = "dataSource" class = "com.htxx.service..MultiDataSource" >
< property name = "dataSource" >
< ref bean = "dataSource1" />
property >
bean >
< bean id = "sessionFactory" class = "org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
< property name = "dataSource" >
< ref bean = "dataSource" />
property >
......
bean >
其中dataSource 屬性實際上更准確地說應當是 defaultDataSource ,即 spring 啟動時以及在客戶沒有指定數據源時應當指定的默認數據源。
該方案的優勢

以上方案與其它方案相比,它有哪些優勢呢?
首 先,這個方案完全是在 spring 的框架下解決的,數據源依然配置在 spring 的配置文件中, sessionFactory依然去配置它 的 dataSource 屬性,它甚至都不知道 dataSource 的改變。唯一不同的是在真正的 dataSource 與 sessionFactory 之間增加了一個 MultiDataSource 。
其 次,實現簡單,易於維護。這個方案雖然我說了這么多東西,其實都是分析,真正需要我們寫的代碼就只有 MultiDataSource 、 SpObserver 兩個類。 MultiDataSource 類真正要寫的只 有 getDataSource() 和getDataSource(sp) 兩個方法,而 SpObserver 類更簡單了。實現越簡單,出錯的可能 就越小,維護性就越高。
最 後,這個方案可以使單數據源與多數據源兼容。這個方案完全不影響 BUS 和 DAO 的編寫。如果我們的項目在開始之初是單數據源的情況下開發,隨著項 目的進行,需要變更為多數據源,則只需要修改 spring 配置,並少量修改 MVC 層以便在請求中寫入需要的數據源名,變更就完成了。如果我們的項 目希望改回單數據源,則只需要簡單修改配置文件。這樣,為我們的項目將增加更多的彈性。
特 別說明:實例中的DynamicLoadBean在web環境下運行會出錯,需要將類中AbstractApplicationContext改為 org.springframework.context.。

熱點內容
手機無線路由器怎麼設置密碼 發布:2025-05-12 05:18:28 瀏覽:815
渝人解壓密碼 發布:2025-05-12 05:18:12 瀏覽:768
備份網站資料庫備份 發布:2025-05-12 05:04:35 瀏覽:52
轉移的存儲卡 發布:2025-05-12 04:51:18 瀏覽:466
c語言大數相加 發布:2025-05-12 04:51:13 瀏覽:589
安卓內存大小有什麼影響 發布:2025-05-12 04:41:36 瀏覽:50
以下c語言常量錯誤的是 發布:2025-05-12 04:40:39 瀏覽:808
怎麼降低qq版本安卓80 發布:2025-05-12 04:40:39 瀏覽:190
一個密碼多少人知道後就不是秘密 發布:2025-05-12 04:26:07 瀏覽:521
ftp埠非21 發布:2025-05-12 04:09:09 瀏覽:229