设为首页 收藏本站
查看: 623|回复: 0

[经验分享] 使用JOTM进行Tomcat的JTA调用

[复制链接]

尚未签到

发表于 2017-1-31 09:09:30 | 显示全部楼层 |阅读模式
  前段时间碰到一个需要访问多个数据库的例子,由于项目上是采用tomcat作为项目开发和布署,所以就没有考虑采用特定厂商的JTA实现,而是通过一个开源的JTA实现来完成tomcat和多个数据库之间的直接交互。
  多数据库访问最直接的问题就是在一个service中,存在着多个数据库dao对象,当前面的dao对象操作完成之后,如果后面的某一个dao访问出错,那么这个service应该如何进行回滚呢。一般来说,回滚应该是整个service一起回滚,所以就需要对这个service中的所有dao所涉及的sessionFactory进行处理。而对于hibernate+spring来说,spring是使用hibernate的sessionFactory来进行事务的控制和回滚的,而hibernate又是将由自己的一个transactionFactory引用相关的transaction来进行事务的提交和回滚。所以,如果要用到多个数据库,就需要一个支持多个数据库的transaction。JOTM就提供了一个开源的多数据库Transaction应用,它采用了支持XADatasource的Xpool来进行数据源管理。
  1,首先需要在项目中引入以下包:

<!--这个为jotm的核心包 -->
<dependency>
<groupId>org.ow2.jotm</groupId>
<artifactId>jotm-core</artifactId>
<version>2.2.1</version>
</dependency>
<!-- 这个为xappol即XaDatasource的一个开源实现 -->
<dependency>
<groupId>com.experlog</groupId>
<artifactId>xapool</artifactId>
<version>1.5.0</version>
</dependency>
<!-- jotm的数据操作类包 -->
<dependency>
<groupId>org.ow2.jotm</groupId>
<artifactId>jotm-datasource</artifactId>
<version>2.2.1</version>
</dependency>
<!-- cmi配置包,jotm初始化时需要相应的包 -->
<dependency>
<groupId>org.ow2.cmi</groupId>
<artifactId>cmi-all</artifactId>
<version>2.0-RC7</version>
</dependency>
<!-- j2ee的api,tomcat中没有中 -->
<dependency>
<groupId>geronimo-spec</groupId>
<artifactId>geronimo-spec-j2ee-connector</artifactId>
<version>1.5-rc4</version>
</dependency>
  2,在配置文件的根目录增加一个carol.properties文件(此文件是一个对命名空间以及jndi的配置支持)

carol.protocols=jrmp
carol.jvm.rmi.local.call=true
carol.start.jndi=false
carol.start.ns=false
carol.jndi.java.naming.factory.url.pkgs=org.apache.naming

  3,在项目中配置数据源连接,这里就不能在spring或者hibernate的配置文件中配置数据源了(当然,如果配置成xadatabase可能会正确,没尝试过)。在web应用中,在webapp下新建立META-INF文件夹,并新建立context.xml文件。(有些文件说直接在tomcat的service.xml中创建,其实在每个项目中建立更加独立)tomcat在加载项目时会自动加载此文件。

<?xml version='1.0' encoding='utf-8'?>
<Context reloadable="false">
<Resource name="jdbc/gtip"
auth="Container"
type="javax.sql.DataSource"
factory="org.objectweb.jotm.datasource.DataSourceFactory"
driverClassName="com.mysql.jdbc.Driver"
username="root" password=""
url="jdbc:mysql://localhost/gtip"/>
<Resource name="jdbc/gtipext"
auth="Container"
type="javax.sql.DataSource"
factory="org.objectweb.jotm.datasource.DataSourceFactory"
driverClassName="com.mysql.jdbc.Driver"
username="root" password=""
url="jdbc:mysql://localhost/gtipext"/>
<Resource name="UserTransaction"
auth="Container"
type="javax.transaction.UserTransaction"/>
<Transaction factory="org.objectweb.jotm.UserTransactionFactory"
jotm.timeout="60"/>
  这里建立了两个数据源,一个为gtip,一个为gtipext,且声明了一个默认的事务UserTransaction,同时声明了一个事务提供工厂,表示由jotm提供了一个事务实现。
  4,在项目中引用这两个数据源,即在web.xml中引用数据源。

<resource-env-ref>
<description>gtip</description>
<resource-env-ref-name>jdbc/gtip</resource-env-ref-name>
<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
</resource-env-ref>
<resource-env-ref>
<description>gtip</description>
<resource-env-ref-name>jdbc/gtipext</resource-env-ref-name>
<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
</resource-env-ref>
  这里即表示需要引用两个数据源定义
  5,在hibernate.cfg.xml中配置数据源,表示引用此数据源

<property name="connection.datasource">java:comp/env/jdbc/gtipext</property>
  这里就会引用gtipext的数据源,表示hibernate将通过此来寻找相应的datasource实现
  6,在spring.xml中配置事务,并通知hibernate引用相关jtaTransactionFactory

<bean id="jotm" class="com.greejoy.develop.bean.JotmFactoryBean"/>
  此是一个jotmBean定义,此bean在Spring3.x版本上已经没有了,所以可以从spring2.5.6版本上直接将源码copy过来即可。这里就是一个工厂bean,去最终创建出一个jotm的current对象(或者不是创建,而是直接通过静态引用Current.getCurrent()直接获取)。在这里,就需要一个手段来获取到jotm对象。

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager" ref="jotm"/>
</bean>

  事务管理器声明,表示定义了一个jta的事务管理器(其实它最没有实现transactionManager接口),但是最终的事务管理将由具体的transactionManager去实现,即将实现transactionManager的工作委派给容器或者具体的实现去做。

<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocations" value="classpath*:conf/**/hibernate.cfg.xml"/>
<property name="jtaTransactionManager" ref="jotm"/>
</bean>

  Hibernate的sessionFactory定义声明,其中需要一个jtaTransactionManager的属性定义,当hibernate解析此属性时,将会指定hibernate的transactionFactory实现为JTATransactionFactory(默认它会指定为JDBCTransactionFactory)。
  至此,相应的配置工作即结束,在项目中可以使用spring跟以前一个的定义事务控制aop,并交由相关的transactionManager去进行控制。
  ps:在spring的AnnotationSessionFactoryBean来说,在配置了jtaTransactionManager之后,spring会往hibernate中配置一个属性hibernate.transaction.manager_lookup_class,并引用hibernate寻找到相应的transactionManager。但是hibernate在3.5.3版本实现中,并没有使用lookupClass来寻找transactionManger,而是使用其去寻找userTransactionName,再自己根据userTransactionName通过initContext来取得transactionManager。在srping3.x的实现中,lookupClass(即LocalTransactionManagerLookup)的getUserTransactionName会返回null(虽然其getTransactionManager会返回相应的transactionManager)。hibernate没有使用这个方法,而是使用了getTransactionUsername方法。两者显示没有很好的对接,或者是其中一个考虑不太周全。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-335569-1-1.html 上篇帖子: win2003下tomcat服务器部署与安全设置 下篇帖子: tomcat架构分析 (connector NIO 实现)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表