一般的企业管理系统免不了要访问多个数据库,如框架数据库、仓库数据库等,但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; } }
相关推荐
spring+druid+AtomikosDataSource实现多数据源切换及分布式事务控制
spring+hibernate+atomikos实现多数据源分布式事务管理
本用例基于 Spring Boot + Druid + Mybatis 配置多数据源,并采用 JTA 实现分布式事务。
Spring boot+Atomikos+JTA+Hibernate+MySQL实现分布式事务+多数据源,分别向两个不同的数据里面插入数据同时失败和成功,调用接口方式原理一样。
使用spring + atomikos+druid配置的分布式事务demo,两种数据源配置方式都可以,使用junit测试没问题,案例中使用的mysql数据库是8.0.11版本,版本不同请自行修改pom.xml和jdbc.properties
NULL 博文链接:https://hanqunfeng.iteye.com/blog/2121427
多数据源,实现分布式事务管理,基于Spring+SpringMVC+MyBatis+Atomikos框架
Spring Boot:mybatis-plus + atomikos + druid 实现不同实例数据库的多数据源配置和分布式事务管理(demo项目),想到工作上可能会用到多数据源,但是自己在这方面并不是很熟悉,于是在网上查阅了很多文章,结果...
springboot+mybatis+druid+atomikos 多数据源,分布式事务,集成websocket,redis,swagger2
Spring+Mybatis+Atomikos实现JAVA初始化并控制多个数据源+分布式事务的一个DEMO,内涵源代码,以及一篇关于该内容的博客
springboot+Atomikos+jpa+mysql的JTA分布式事务实现,本案例涉及到2个数据库,预期结果,在同一个事务中,两个库的状态一致
将基于Spring4.1.7+atomikos+mybaits 实现两阶段的分布式事务处理,通过AOP面向切面实现动态实现数据源的切换 http://www.dczou.com/viemall/407.html
由于网上的多数据源事务的帖子大多是2010年以前的,现在spring都已经到4.X了,有些类已经弃用了。 原先很多都是用jotm实现的,但是由于spring的升级,totm的本地化实例那个类已经找不到了,所以我使用了atomikos。 ...
spring+druid+atomikos分布式事务,多数据源切换!其中包括配置文件
基于XA的非Maven 基于SpringMVC+Spring+MyBatis+Atomikos的分布式事务处理案例源码,亲自测试可以使用。能SSM多数据源环境和分布式环境下事务处理问题.
Spring多数据源分布式事务管理/springmvc+spring+atomikos[jta]+druid+mybatis
开发工具:MyEclipse10, 数据库:Mysql, demo中使用了2个数据源,2个不同的Mysql数据库。 注:不同数据库dataSource的配置是不一样的
spring+mybatis+mysql+atomikos,实现一个简单的多数据源事物控制程序
spring+atomikos+mybatis 多数据源事务(动态切换)
使用Atomikos支持分布式事务,Spring+Mybatis+Druid+AtomikosDataSource 使用手册: https://www.yuque.com/itman/wosfkn/mreame