Ssh多数据源解决方案
Ssh多数据源是个常见的问题,本人根据网上的资料,采用目前最先进的技术,经过调试解决了这个问题,可以连多个端口的多个模式的多张表。主要用到spring3的动态数据源技术,系统只有一个sessionFactory,用到某数据源时,用一条语句指定此数据源即可。各dataSource采用com.mchange.v2.c3p0.ComboPooledDataSource,c3p0提供连接池,不用每次连接数据库,大大提高效率。系统用到的是国产最先进的达梦数据库,配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 开启注解处理器 -->
<context:annotation-config/>
<!-- 定义使用C3P0连接池的数据源 -->
<bean id="dataSourceA"class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<!-- 指定连接数据库的JDBC驱动 -->
<propertyname="driverClass">
<value>dm.jdbc.driver.DmDriver</value>
</property>
<!-- 连接数据库所用的URL -->
<propertyname="jdbcUrl">
<value>jdbc:dm://192.168.1.250:5236</value>
</property>
<!-- 连接数据库的用户名 -->
<propertyname="user">
<value>sysdba</value>
</property>
<!-- 连接数据库的密码 -->
<propertyname="password">
<value>222</value>
</property>
<!-- 设置数据库连接池的最大连接数 -->
<propertyname="maxPoolSize">
<value>20</value>
</property>
<!-- 设置数据库连接池的最小连接数 -->
<propertyname="minPoolSize">
<value>2</value>
</property>
<!-- 设置数据库连接池的初始化连接数 -->
<propertyname="initialPoolSize">
<value>2</value>
</property>
<!-- 设置数据库连接池的连接的最大空闲时间,单位为秒 -->
<propertyname="maxIdleTime">
<value>20</value>
</property>
</bean>
<!-- 定义使用C3P0连接池的数据源(基础库数据源) -->
<bean id="dataSourceB"class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<!-- 指定连接数据库的JDBC驱动 -->
<propertyname="driverClass">
<value>dm.jdbc.driver.DmDriver</value>
</property>
<!-- 连接数据库所用的URL -->
<propertyname="jdbcUrl">
<value>jdbc:dm://192.168.1.250:5237</value>
</property>
<!-- 连接数据库的用户名 -->
<propertyname="user">
<value>sysdba</value>
</property>
<!-- 连接数据库的密码 -->
<propertyname="password">
<value>222</value>
</property>
<!-- 设置数据库连接池的最大连接数 -->
<propertyname="maxPoolSize">
<value>20</value>
</property>
<!-- 设置数据库连接池的最小连接数 -->
<propertyname="minPoolSize">
<value>2</value>
</property>
<!-- 设置数据库连接池的初始化连接数 -->
<propertyname="initialPoolSize">
<value>2</value>
</property>
<!-- 设置数据库连接池的连接的最大空闲时间,单位为秒 -->
<propertyname="maxIdleTime">
<value>20</value>
</property>
</bean>
<!-- 定义使用C3P0连接池的数据源(测试数据源) -->
<bean id="dataSourceC"class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<!-- 指定连接数据库的JDBC驱动 -->
<propertyname="driverClass">
<value>dm.jdbc.driver.DmDriver</value>
</property>
<!-- 连接数据库所用的URL -->
<propertyname="jdbcUrl">
<value>jdbc:dm://192.168.1.250:5238</value>
</property>
<!-- 连接数据库的用户名 -->
<propertyname="user">
<value>sysdba</value>
</property>
<!-- 连接数据库的密码 -->
<propertyname="password">
<value>222</value>
</property>
<!-- 设置数据库连接池的最大连接数 -->
<propertyname="maxPoolSize">
<value>20</value>
</property>
<!-- 设置数据库连接池的最小连接数 -->
<propertyname="minPoolSize">
<value>2</value>
</property>
<!-- 设置数据库连接池的初始化连接数 -->
<propertyname="initialPoolSize">
<value>2</value>
</property>
<!-- 设置数据库连接池的连接的最大空闲时间,单位为秒 -->
<propertyname="maxIdleTime">
<value>20</value>
</property>
</bean>
<bean id="dynamicDataSource"class="com.hjzbjcxcyw.action.common.DynamicDataSource">
<!-- 通过key-value的形式来关联数据源 -->
<propertyname="targetDataSources">
<mapkey-type="java.lang.String">
<entryvalue-ref="dataSourceA" key="dataSourceA"></entry>
<entryvalue-ref="dataSourceB" key="dataSourceB"></entry>
<entryvalue-ref="dataSourceC" key="dataSourceC"></entry>
</map>
</property>
<propertyname="defaultTargetDataSource" ref="dataSourceA">
</property>
</bean>
<!-- 定义Hibernate的SessionFactory-->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!-- 依赖注入上面定义的数据源dataSource -->
<propertyname="dataSource" ref="dynamicDataSource"/>
<!-- 注册Hibernate的ORM映射文件 -->
<property name="mappingResources">
<list>
<value>com/hjzbjcxcyw/po/test/liwh/Book3.hbm.xml</value>
<value>com/hjzbjcxcyw/po/test/liwh/Book.hbm.xml</value>
<value>com/hjzbjcxcyw/po/test/liwh/Department.hbm.xml</value>
<value>com/hjzbjcxcyw/po/test/liwh/Employee.hbm.xml</value>
<value>com/hjzbjcxcyw/po/test/liwh/Bookb.hbm.xml</value>
</list>
</property>
<!-- 设置Hibernate的相关属性 -->
<propertyname="hibernateProperties">
<props>
<propkey="hibernate.cache.user_second_level_cache">false</prop>
<!-- 设置Hibernate的数据库方言 -->
<propkey="hibernate.dialect">org.hibernate.dialect.DmDialect</prop>
<!-- 设置Hibernate是否在控制台输出SQL语句,开发调试阶段通常设为true -->
<propkey="show_sql">true</prop>
<!-- 设置Hibernate一个提交批次中的最大SQL语句数 -->
<propkey="hibernate.jdbc.batch_size">50</prop>
</props>
</property>
</bean>
<!--定义Hibernate的事务管理器HibernateTransactionManager-->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<!-- 依赖注入上面定义的sessionFactory -->
<propertyname="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 定义一个事务通知txAdvice,配置事务的传播特性 -->
<tx:adviceid="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 所有以browse、list、load、get及 is开头的业务逻辑方法均不需要事务控制且只读 -->
<tx:methodname="browse*" propagation="NOT_SUPPORTED"
read-only="true"/>
<tx:methodname="list*" propagation="NOT_SUPPORTED"
read-only="true"/>
<tx:methodname="load*" propagation="NOT_SUPPORTED"
read-only="true"/>
<tx:methodname="get*" propagation="NOT_SUPPORTED"
read-only="true"/>
<tx:methodname="is*" propagation="NOT_SUPPORTED"
read-only="true"/>
<!-- 所有以add开头的业务逻辑方法均需要事务控制-->
<tx:methodname="add*" propagation="REQUIRED" />
<!-- 设置所有方法均进行事务控制,如果当前没有事务,则新建一个事务 -->
<tx:methodname="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- 定义一个事务通知txAdvice,配置事务的传播特性 -->
<!-- 装配HibernateTemplate实例 -->
<bean id="hibernateTemplate"class="org.springframework.orm.hibernate3.HibernateTemplate">
<constructor-argref="sessionFactory" />
</bean>
<!-- 装配通用数据库访问类BaseDAOImpl -->
<bean id="dao"class="com.hjzbjcxcyw.dao.BaseDAOImpl">
<propertyname="hibernateTemplate" ref="hibernateTemplate"/>
</bean>
</beans>
Book3.hbm.xml文件如下:
<?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">
<hibernate-mapping>
<class name="com.hjzbjcxcyw.po.test.liwh.Book3"table='"liwh"."BOOK3"'>(liwh是模式名,BOOK3是表名)
<id name="id"column="id" type="java.lang.String" length="36">
<generatorclass="assigned" />
</id>
<propertyname="bookName" type="java.lang.String">
<columnname="BOOK_NAME" length="50" />
</property>
<propertyname="isbn" type="java.lang.String">
<columnname="ISBN" length="256" />
</property>
<propertyname="author" type="java.lang.String">
<columnname="AUTHOR" length="50" />
</property>
<propertyname="title" type="java.lang.String">
<columnname="TITLE" length="50" />
</property>
<propertyname="date" type="java.util.Date">
<columnname="date" />
</property>
<propertyname="ids" type="java.lang.String">
<columnname="IDS" length="22" />
</property>
</class>
</hibernate-mapping>
DynamicDataSource.action//动态分配数据源
packagecom.hjzbjcxcyw.action.common;
importorg.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
publicclassDynamicDataSourceextends AbstractRoutingDataSource {
@Override
protectedObject determineCurrentLookupKey() {
returnDataSourceContextHolder.getProxType();
}
}
DataSourceContextHolder.action//设置数据源
packagecom.hjzbjcxcyw.action.common;
publicclassDataSourceContextHolder {
publicstatic final StringDATA_SOURCE_A ="dataSourceA";
publicstatic final StringDATA_SOURCE_B ="dataSourceB";
publicstatic final StringDATA_SOURCE_C ="dataSourceC";
privatestatic final ThreadLocal<String>contextHolder =new ThreadLocal<String>();
publicstatic void setProxType(String customerType) {
contextHolder.set(customerType);
}
publicstatic String getProxType() {
returncontextHolder.get();
}
publicstatic void clearProxType() {
contextHolder.remove();
}
}
Tools.action//指定数据源
publicstatic void setDataSource(int h){
if(h==1)
DataSourceContextHolder.setProxType(DataSourceContextHolder.DATA_SOURCE_A);
elseif(h==2)
DataSourceContextHolder.setProxType(DataSourceContextHolder.DATA_SOURCE_B);
elseif(h==3)
DataSourceContextHolder.setProxType(DataSourceContextHolder.DATA_SOURCE_C);
}
在service文件的各个方法中指定数据源。
publicList<Employee> browseEmployee() {
Tools.setDataSource(3);
List<Employee>l = dao.listAll("Employee");
System.out.println("booksize=" + l.size());
returnl;
}
在acton文件中调用service的browseEmployee()方法。
大功告成,呵呵!
2013-04-01