spring+hibernate配置多数据源及多个事务过程
- 在datasource.properties文件中增加数据库配置
sqlServer.jdbc.url=jdbc:sqlserver://127.0.0.1:1433;databaseName=db_ceshi1 sqlServer.jdbc.user=sa sqlServer.jdbc.password=sa sqlServer.jdbc.initialPoolSize=5 sqlServer.jdbc.minPoolSize=5 sqlServer.jdbc.maxPoolSize=80 sqlServer.jdbc.checkoutTimeout=20000 sqlServer.jdbc.idleConnectionTestPeriod=120 sqlServer.jdbc.maxIdleTime=60 sqlServer.jdbc.maxStatements=6000 sqlServer.jdbc.testConnectionOnCheckout=false sqlServer.jdbc.erms.driverClass=com.microsoft.sqlserver.jdbc.SQLServerDriver sqlServer.jdbc.erms.url=jdbc:sqlserver://127.0.0.1:1433;databaseName=db_ceshi2 sqlServer.jdbc.erms.user=sa sqlServer.jdbc.erms.password=sa sqlServer.jdbc.erms.initialPoolSize=5 sqlServer.jdbc.erms.minPoolSize=5 sqlServer.jdbc.erms.maxPoolSize=80 sqlServer.jdbc.erms.checkoutTimeout=20000 sqlServer.jdbc.erms.idleConnectionTestPeriod=120 sqlServer.jdbc.erms.maxIdleTime=60 sqlServer.jdbc.erms.maxStatements=6000 sqlServer.jdbc.erms.testConnectionOnCheckout=false
- 在spring.xml文件中配置数据源级事务
<bean id="dataSourceSqlServer" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${sqlServer.jdbc.driverClass}" /> <property name="jdbcUrl" value="${sqlServer.jdbc.url}" /> <property name="user" value="${sqlServer.jdbc.user}" /> <property name="password" value="${sqlServer.jdbc.password}" /> <property name="initialPoolSize" value="${sqlServer.jdbc.initialPoolSize}" /> <property name="minPoolSize" value="${sqlServer.jdbc.minPoolSize}" /> <property name="maxPoolSize" value="${sqlServer.jdbc.maxPoolSize}" /> <property name="checkoutTimeout" value="${sqlServer.jdbc.checkoutTimeout}" /> <property name="idleConnectionTestPeriod" value="${sqlServer.jdbc.idleConnectionTestPeriod}" /> <property name="maxIdleTime" value="${sqlServer.jdbc.maxIdleTime}" /> <property name="maxStatements" value="${sqlServer.jdbc.maxStatements}" /> <property name="testConnectionOnCheckout" value="${sqlServer.jdbc.testConnectionOnCheckout}" /> </bean> <bean id="dataSource" class="com.hebky.erms.util.core.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="dataSourceMySql" value-ref="dataSourceMySql" /> <entry key="dataSourceSqlServer" value-ref="dataSourceSqlServer" /> </map> </property> <property name="defaultTargetDataSource" ref="dataSourceSqlServer" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:hibernate.cfg.xml" /> <!-- 通过扫描包的方式扫描所有实体类 --> <property name="packagesToScan"> <list> <value>com.ceshi.*</value> </list> </property> </bean> <!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> <property name="nestedTransactionAllowed" value="true"></property> </bean> <!-- 拦截器方式配配置事务 --> <tx:advice id="txadvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="saveRN*" propagation="REQUIRES_NEW" /> <tx:method name="import*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="saveNS*" propagation="NOT_SUPPORTED" /> <tx:method name="updateNS*" propagation="NOT_SUPPORTED" /> <tx:method name="executeNS*" propagation="REQUIRED" /> <tx:method name="updateRN*" propagation="REQUIRES_NEW" /> <tx:method name="delete*" propagation="REQUIRED" no-rollback-for="NotImplementedException"/> <tx:method name="get*" read-only="true" propagation="REQUIRED" /> <tx:method name="find*" read-only="true" propagation="REQUIRED" /> <tx:method name="query*" read-only="true" propagation="REQUIRED" /> <tx:method name="count*" read-only="true" propagation="REQUIRED" /> <tx:method name="isNS*" read-only="true" propagation="NOT_SUPPORTED" /> <tx:method name="*" read-only="true" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="serviceMethods" expression="execution(* com.ceshi..service..*.*(..))" /> <aop:advisor advice-ref="txadvice" pointcut-ref="serviceMethods" /> </aop:config> <!--从数据库配置--> <bean id="dataSourcecm" class="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name="driverClass" value="${sqlServer.jdbc.erms.driverClass}" /> <property name="jdbcUrl" value="${sqlServer.jdbc.erms.url}" /> <property name="user" value="${sqlServer.jdbc.erms.user}" /> <property name="password" value="${sqlServer.jdbc.erms.password}" /> <property name="initialPoolSize" value="${sqlServer.jdbc.erms.initialPoolSize}" /> <property name="minPoolSize" value="${sqlServer.jdbc.erms.minPoolSize}" /> <property name="maxPoolSize" value="${sqlServer.jdbc.erms.maxPoolSize}" /> <property name="checkoutTimeout" value="${sqlServer.jdbc.erms.checkoutTimeout}" /> <property name="idleConnectionTestPeriod" value="${sqlServer.jdbc.erms.idleConnectionTestPeriod}" /> <property name="maxIdleTime" value="${sqlServer.jdbc.erms.maxIdleTime}" /> <property name="maxStatements" value="${sqlServer.jdbc.erms.maxStatements}" /> <property name="testConnectionOnCheckout" value="${sqlServer.jdbc.erms.testConnectionOnCheckout}" /> </bean> <!--session工厂--> <bean id="sessionFactorycm" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" > <property name="dataSource" ref="dataSourcecm" /> <!--包扫描,数据库对应的实体类所在的包--> <!-- 通过扫描包的方式扫描所有实体类 --> <property name="packagesToScan"> <list> <value>com.ceshi.*</value> </list> </property> <property name="hibernateProperties"> <value> <!-- hibernate使用的数据库方言(即连接哪种数据库) --> hibernate.dialect = org.hibernate.dialect.SQLServerDialect <!-- 自动更新数据库表结构 --> hibernate.hbm2ddl.auto = update <!-- 后台显示sql语句,开发时使用--> hibernate.show_sql = true <!-- 是否格式化SQL --> hibernate.format_sql = true </value> </property> </bean> <!--事务管理器--> <bean id="transactionManagercm" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactorycm"/> </bean> <!-- 配置事务通知属性 --> <tx:advice id="transactionAdvicecm" transaction-manager="transactionManagercm"> <!-- 定义事务传播属性 --> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="saveRN*" propagation="REQUIRES_NEW" /> <tx:method name="import*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="saveNS*" propagation="NOT_SUPPORTED" /> <tx:method name="updateNS*" propagation="NOT_SUPPORTED" /> <tx:method name="executeNS*" propagation="REQUIRED" /> <tx:method name="updateRN*" propagation="REQUIRES_NEW" /> <tx:method name="delete*" propagation="REQUIRED" no-rollback-for="NotImplementedException"/> <tx:method name="get*" read-only="true" propagation="REQUIRED" /> <tx:method name="find*" read-only="true" propagation="REQUIRED" /> <tx:method name="query*" read-only="true" propagation="REQUIRED" /> <tx:method name="count*" read-only="true" propagation="REQUIRED" /> <tx:method name="isNS*" read-only="true" propagation="NOT_SUPPORTED" /> <tx:method name="*" read-only="true" /> </tx:attributes> </tx:advice> <!-- 配置事务切面 --> <aop:config> <aop:advisor pointcut="execution(* com.ceshi..service..*.*(..))" advice-ref="transactionAdvicecm"/> </aop:config>
- 创建DatabaseContextHolder类
class DatabaseContextHolder { public static final String DATA_SOURCE_SQLSERVER = "dataSourceSqlServer"; public static final String DATA_SOURCE_ERMS = "dataSourcecm"; private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); // 线程本地环境 /** * 设置数据源类型 * * @param customerType 数据源类型 */ public static void setCustomerType(String customerType) { contextHolder.set(customerType); } /** * 获取数据源类型 * * @return */ static String getCustomerType() { return contextHolder.get(); } /** * 清除数据源类型 */ public static void clearCustomerType() { contextHolder.remove(); } }
- 创建DynamicDataSource继承AbstractRoutingDataSource获取动态数据源
public class DynamicDataSource extends AbstractRoutingDataSource { /** * 在进行DAO操作前,通过上下文环境变量,获得数据源的类型 */ @Override protected Object determineCurrentLookupKey() { return DatabaseContextHolder.getCustomerType(); } }
- 在BaseDao中注入session即可
public abstract class BaseDao implements IBaseDao { @Resource private SessionFactory sessionFactory;// 从容器中注入session工厂【无需get,set方法】 @Resource private SessionFactory sessionFactorycm; /** * 向子类暴露的接口获用来获取session * * @return session */ protected Session getSession() { // 事务必须是开启的(Required),否则获取不到 return sessionFactory.getCurrentSession(); } //注入第二个session protected Session getSessionFactorycm(){ return sessionFactorycm.getCurrentSession(); } /** * 保存实体 * * @param t 实体参数 */ public <T> void save(T t) { getSession().save(t); } public <T> void saveTwo(T t){ getSessionFactorycm().save(T); }
}
配置多数据源完成