在Hibernate内里动态切换SChema实现会见差异的数据库的几种要领
副标题#e#
需求很简朴,沟通的操纵,好比表布局完全沟通,措施也完全沟通,但需要按照某些条件,别离向差异的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系统只有一个。
#p#副标题#e#
要领二:
利用多重设置,好比针对天津和北京,我们别离编写对应的映射文件
<?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);
这样就可以实现动态挪用了。
#p#分页标题#e#
至于placeName,可以通过前台挪用措施通报过来,也可以放到ThreadLocal内里,后者更具有通用性,并且对以前的措施修改量最少,因为只需要写一个getPlaceName()得要领就行了。
要领3:
修改数据库的毗连属性,将以前指向SchemaA的改成指向SchemaB,这需要一些高权限的账号做这些工作。
其实,尚有一个更简朴的要领,那就是本身担任一个DataSource,然后在要领内里,按照ThreadLocal的参数,返回差异的数据毗连。好比假如是BEIGJING,则返回 BeiJingDatasource的毗连,假如是TIANJIN,则返回TianJinDatasource的毗连。
系统在利用时,必定会从DataSource内里获取毗连,我们在内部做了分派,自然前台运行功效也就分派开了。
提示:在你的DataSource内里可以包括Map<String,DataSource>这样的布局,来做内部的转发。
小我私家总结:
第一种要领只适合于单机,单线程利用。
第二个要领,相对技能难度低一点,单设置起来要写多份,维护较量贫苦
第三个要领,技能难度高,单维护起来简朴
我小我私家虽然是用第三个要领了,很有趣。