程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 在Hibernate裡面動態切換SChema實現訪問不同的數據庫的幾種方法

在Hibernate裡面動態切換SChema實現訪問不同的數據庫的幾種方法

編輯:關於JAVA

需求很簡單,相同的操作,比如表結構完全相同,程序也完全相同,但需要根據某些條件,分別向不同的schema做操作。

比如,如果當前處理的是A公司,那麼向SchemaA 裡面保存數據,如果當前處理的是B公司的,則向SchemaB裡面保存數據。

其實就是一套程序,實現後台的動態切換。

我這裡提供幾種方法,大家自己根據情況考慮,都能實現,注意是實現,不一定適合於正式應用。

方法一:

在Hibernate裡面,有一個配置參數,比如下面這個帶Schema配置的映射

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="com.csc.poimanager.dao.Poi" table="POI" schema="P_BEIJING">
<id name="poiId" type="java.lang.Long">
<column name="POI_ID" precision="10" scale="0" />
<generator class="increment" />
</id>
<property name="cnName" type="java.lang.String">
<column name="CN_NAME" length="1000" />
</property>
</class>
</hibernate-mapping>

其中的schema="P_BEIJING"將 Schema寫死了。

我們可以不寫這部分,而是使用系統的配置參數

<property name="hibernate.default_schema">POI_BEIJING</property>

這樣的話,我們的映射文件就變成了

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="com.csc.poimanager.dao.Poi" table="POI"">
<id name="poiId" type="java.lang.Long">
<column name="POI_ID" precision="10" scale="0" />
<generator class="increment" />
</id>
<property name="cnName" type="java.lang.String">
<column name="CN_NAME" length="1000" />
</property>
</class>
</hibernate-mapping>

在調用的時候,動態的指定Schema的參數就行了,比如

public static SessionFactory rebuildSessionFactoryForChangeSchema(String newSchema){
try {
Properties p = configuration.getProperties();
System.out.println("---" + p);
p.put("hibernate.default_schema", newSchema);
sessionFactory = configuration.buildSessionFactory();
System.out.println(" change schema successfully ......... ");
return sessionFactory;
} catch (Exception e) {
System.err
.println("%%%% rebuild session factory failed for changing schema %%%%");
e.printStackTrace();
return null;
}
}

這個方法能實現切換,但是我們必須每次都返回一個SessionFactory, 否則在並發的時候就會出問題。因為hibernate.default_schema系統只有一個。

方法二:

使用多重配置,比如針對天津和北京,我們分別編寫對應的映射文件

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
<class name="com.csc.poimanager.dao.Poi" table="POI" id="P_BEIJING" schema="P_BEIJING">
<id name="poiId" type="java.lang.Long">
<column name="POI_ID" precision="10" scale="0" />
<generator class="increment" />
</id>
<property name="cnName" type="java.lang.String">
<column name="CN_NAME" length="1000" />
</property>
</class>
<class name="com.csc.poimanager.dao.Poi" id="P_TIANJIN" table="POI" schema="P_TIANJIN">
<id name="poiId" type="java.lang.Long">
<column name="POI_ID" precision="10" scale="0" />
<generator class="increment" />
</id>
<property name="cnName" type="java.lang.String">
<column name="CN_NAME" length="1000" />
</property>
</class>
</hibernate-mapping>

配置文件除了SCHEMA和ID不同外,其它的完全相同,那麼如何使用呢?

sessionFactory.getBean("P"+placeName);

這樣就可以實現動態調用了。

至於placeName,可以通過前台調用程序傳遞過來,也可以放到ThreadLocal裡面,後者更具有通用性,而且對以前的程序修改量最少,因為只需要寫一個getPlaceName()得方法就行了。

方法3:

修改數據庫的連接屬性,將以前指向SchemaA的改成指向SchemaB,這需要一些高權限的賬號做這些事情。

其實,還有一個更簡單的方法,那就是自己繼承一個DataSource,然後在方法裡面,根據ThreadLocal的參數,返回不同的數據連接。比如如果是BEIGJING,則返回 BeiJingDatasource的連接,如果是TIANJIN,則返回TianJinDatasource的連接。

系統在使用時,肯定會從DataSource裡面獲取連接,我們在內部做了分配,自然前台運行結果也就分配開了。

提示:在你的DataSource裡面可以包含Map<String,DataSource>這樣的結構,來做內部的轉發。

個人總結:

第一種方法只適合於單機,單線程使用。

第二個方法,相對技術難度低一點,單配置起來要寫多份,維護比較麻煩

第三個方法,技術難度高,單維護起來簡單

我個人當然是用第三個方法了,很有趣。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved