spring + atomikos解决多数据源事务管理
2016-01-27 10:39
483 查看
一般的企业管理系统免不了要访问多个数据库,如框架数据库、仓库数据库等,但spring的jdbc事务只支持一个数据源的事务配置,为了在tomcat中支持多数据源事务,可以采用开源框架atomikos来进行配置。
采用的开发环境:Spring4 + hibernate4 + atomikos3.9.3 + mssql2008
1.下载atomikos-jdbc:3.9.1
所需要的包如下:
2.下载sqljdbc4.jar
有关mssql的XA支持,请参考下面:
https://technet.microsoft.com/zh-cn/library/aa342335.aspx
3.Spring atomikos事务配置
配置两个xa数据源xaDataSource,两个SessionFactory
<?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:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd" > <context:component-scan base-package="com.framework.dao"/> <context:component-scan base-package="com.framework.dao.mssql"/> <context:component-scan base-package="com.framework.service"/> <context:component-scan base-package="com.framework.action"/> <context:component-scan base-package="com.stk.dao.mssql"/> <context:component-scan base-package="com.stk.service"/> <context:component-scan base-package="com.stk.action"/> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:framework.properties"/> </bean> <bean class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close" id="datasourceFW"> <property name="uniqueResourceName"><value>framework</value></property> <property name="xaDataSourceClassName" value="com.microsoft.sqlserver.jdbc.SQLServerXADataSource" /> <property name="xaProperties"> <props> <prop key="user">${jdbc.username}</prop> <prop key="password">${jdbc.password}</prop> <prop key="URL">${jdbc.url}</prop> </props> </property> </bean> <bean id="sessionFactoryFW" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="datasourceFW"/> <!-- --> <property name="packagesToScan" value="com.framework.domain"/> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">com.util.SQLServerDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.current_session_context_class">jta</prop> <prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory</prop> </props> </property> </bean> <bean id="hibernateTemplateFW" class="org.springframework.orm.hibernate4.HibernateTemplate" p:sessionFactory-ref="sessionFactoryFW" /> <bean class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close" id="datasourceStk"> <property name="uniqueResourceName"><value>stk</value></property> <property name="xaDataSourceClassName" value="com.microsoft.sqlserver.jdbc.SQLServerXADataSource" /> <property name="xaProperties"> <props> <prop key="user">${jdbcstk.username}</prop> <prop key="password">${jdbcstk.password}</prop> <prop key="URL">${jdbcstk.url}</prop> </props> </property> </bean> <bean id="sessionFactoryStk" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="datasourceStk"/> <!-- --> <property name="packagesToScan" value="com.stk.domain"/> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">com.util.SQLServerDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.current_session_context_class">jta</prop> <prop key="hibernate.transaction.factory_class">org.hibernate.engine.transaction.internal.jta.JtaTransactionFactory</prop> <!-- 4.0 <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop> <prop key="hibernate.cache.use_second_level_cache">true</prop>--> </props> </property> </bean> <bean id="hibernateTemplateStk" class="org.springframework.orm.hibernate4.HibernateTemplate" p:sessionFactory-ref="sessionFactoryStk" /> <!-- atomikos事务管理器 --> <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <description>UserTransactionManager</description> <property name="forceShutdown"> <value>true</value> </property> </bean> <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"> <property name="transactionTimeout" value="300" /> </bean> <!-- spring 事务管理器 --> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager" ref="atomikosTransactionManager"/> <property name="userTransaction" ref="atomikosUserTransaction" /> <property name="allowCustomIsolationLevels" value="true"/> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="select*" read-only="true" propagation="REQUIRED"/> <tx:method name="get*" read-only="true" propagation="REQUIRED"/> <tx:method name="load*" 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="read*" read-only="true" propagation="REQUIRED"/> <tx:method name="sync*"/> <tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="pointcut" expression="execution(* com.framework.service.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"/> </aop:config> </beans>
4.Spring DAO设计
采用SessionFactory注入的方式(不能采用HibernateTemplate)
BaseDao设计,session的管理,采用 ThreadLocal进行保存和获取,保证同一线程获取一次,
注意,数据操作之后要调用session.flush()进行保存。
/** * DAO基类,其它DAO可以直接继承这个DAO,不但可以复用共用的方法,还可以获得泛型的好处。 */ public abstract class BaseDao<T> { ThreadLocal<Session> localSession = new ThreadLocal<Session>(); private Class<T> entityClass; public abstract SessionFactory getSessionFactory(); /** * 通过反射获取子类确定的泛型类 */ public BaseDao() { Type genType = getClass().getGenericSuperclass(); Type[] params = ((ParameterizedType) genType).getActualTypeArguments(); entityClass = (Class) params[0]; } /** * 根据ID加载PO实例 * * @param id * @return 返回相应的持久化PO实例 */ public T load(Serializable id) { return (T) getSession().load(entityClass, id); } /** * 根据ID获取PO实例 * * @param id * @return 返回相应的持久化PO实例 */ public T get(Serializable id) { return (T) getSession().get(entityClass, id); } /** * 保存PO * * @param entity */ public void save(T entity) { Session session = getSession(); session.save(entity); session.flush(); } public void saveOrUpdate(T entity) { Session session = getSession(); session.saveOrUpdate(entity); session.flush(); } /** * 删除PO * * @param entity */ public void remove(T entity) { Session session = getSession(); session.delete(entity); session.flush(); } /** * 更改PO * * @param entity */ public void update(T entity) { Session session = getSession(); session.update(entity); session.flush(); } public Query createSqlQuery(String sql, Object... values) { Assert.hasText(sql); Query query = getSession().createSQLQuery(sql); for (int i = 0; i < values.length; i++) { query.setParameter(i, values[i]); } return query; } public Session getSession() { //Session session =getSessionFactory().getCurrentSession(); //if (session == null) Session session = localSession.get(); if(session == null) { session = getSessionFactory().openSession(); localSession.set(session); } return session; } }框架DAO,FrameworkDao,通过自动注入方式获取sessionFactory,所有框架的数据库DAO操作都继承这个FrameworkDao.
public class FrameworkDao<T> extends BaseDao<T> { @Autowired private SessionFactory sessionFactoryFW; @Override public SessionFactory getSessionFactory() { return sessionFactoryFW; } }仓库数据库DAO,StkDao,也是通过自动注入方式获取sessionFactory,所有仓库的数据库DAO操作都继承这个StkDao.
public class StkDao<T> extends BaseDao<T> { @Autowired private SessionFactory sessionFactoryStk; @Override public SessionFactory getSessionFactory() { return sessionFactoryStk; } }阅读更多
相关文章推荐
- Spring3.0+Hibernate+Atomikos集成构建JTA的分布式事务--解决多数据源跨库事务
- Spring3.0+Hibernate+Atomikos集成构建JTA的分布式事务--解决多数据源跨库事务
- Java之——Spring4+Hibernate4+Atomikos3.3多数据源事务管理
- Spring+Hibernate+Atomikos集成构建JTA的分布式事务--解决多数据源跨库事务
- Spring + Atomikos配置多个数据源,并且管理事务
- Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis
- Spring3.0+Hibernate+Atomikos多数据源分布式事务管理
- Spring+Hibernate+Atomikos集成构建JTA的分布式事务--解决多数据源跨库事务
- Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis
- atomikos + druid + spring 多数据源分布式事务
- Spring Boot多数据源及其事务管理配置方法
- spring4+mybatis3+atomikos3.9多数据源分布式事务控制
- atomikos实现多数据源支持分布式事务管理(spring、tomcat、JTA)
- atomikos - 多数据源事务管理
- 关于spring3.0 后的 事务注解管理指定数据源问题
- Spring和hibernate多个数据源的事务管理
- Spring和hibernate多个数据源的事务管理
- 解决spring 事务管理默认不支持SQLException等运行时异常
- spring+atomikos+mybatis 多数据源事务(动态切换)
- SpringBoot多数据源事务管理机制