程序员人生 网站导航

EJB(四)JPA 分布式事务处理

栏目:框架设计时间:2015-01-10 08:50:15

JPA:全称java persistence API jpa作为j2ee的基础规范之1,也是目前作为比较流行ORM框架之1。不单单作为1种通用的标准ORM解决方案,也是企业级开发散布式事务的1种选择。

 

JTA:全称java transaction API。可以在多个组件或利用之间进行事务处理,相比JDBC来说支持更多的数据源。

 

Ejb3.0对散布式事务也有支持,常常和EntityManager1起使用。下面是针对多个数据源的事务管理的代码实现和在调试进程中的1些调式日志。

 

环境

          jboss⑸.0.0.GA  jdk 1.6 

 MyEclipse

 Version:10.0

 Buildid: 10.0⑵0111028

Code

EJB bean

实体配置

Person

package com.cfl.jpa; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Person implements Serializable{ @Id @GeneratedValue private int id; private String age; private String height; public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getHeight() { return height; } public void setHeight(String height) { this.height = height; } }

Persistent.xml 

JPA 配置文件,配置多个数据源的文件配置

<?xml version="1.0" encoding="UTF⑻"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="test1" transaction-type="JTA"> <!-- mysql数据源 --> <jta-data-source>java:/MySqlDS1</jta-data-source> <!-- 实体类 --> <class>com.cfl.jpa.User</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <!-- <jta-data-source>java:/MyOracleDS</jta-data-source> --> <properties> <!-- 数据库方言 --> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> <!-- <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/> --> <!-- 自动创建 --> <property name="hibernate.hbm2ddl.auto" value="create" /> <!-- 显示sql语句 --> <property name="hibernate.show_sql" value="true" /> </properties> </persistence-unit> <persistence-unit name="test2" transaction-type="JTA"> <jta-data-source>java:/MySqlDS2</jta-data-source> <class>com.cfl.jpa.Person</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <!-- <jta-data-source>java:/MyOracleDS</jta-data-source> --> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> <!-- <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/> --> <property name="hibernate.hbm2ddl.auto" value="create" /> <property name="hibernate.show_sql" value="true" /> </properties> </persistence-unit> </persistence>

EntityManager 

       这个不同数据源的实体管理器需求配置,默许情况只会更新1个数据源。

package com.cfl.jpa; import javax.ejb.Remote; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @Stateless(name="UM") @Remote public class UserManagerImpl implements UserManager { /* * 如果只有1个unitName就无需书写这个,如果有两个unitName就需要 * 来指定哪一个unitName的名称了 */ @PersistenceContext(unitName="test1") private EntityManager em1; @PersistenceContext(unitName="test2") private EntityManager em2; public void addUser() { User user=new User(); user.setAge("23"); em1.persist(user); Person p=new Person(); p.setAge("24"); p.setHeight("1.7"); em2.persist(p); //如果抛出异常则来自两个数据源的保存操作都会回滚,这就是跨域的事务处理 //throw new RuntimeException("回滚事务exception"); //System.out.print("u & p 保存成功!"); } }

在jboss的数据源配置

         需要注意的是数据源的名称和对应连接到数据库的url。

<?xml version="1.0" encoding="UTF⑻"?> <!-- $Id: mysql-ds.xml 41017 2006-02-07 14:26:14Z acoliver $ --> <!-- Datasource config for MySQL using 3.0.9 available from: http://www.mysql.com/downloads/api-jdbc-stable.html --> <datasources> <local-tx-datasource> <jndi-name>MySqlDS1</jndi-name> <connection-url>jdbc:mysql://localhost:3306/MyUser</connection-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <user-name>cfl</user-name> <password>123456</password> <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name> <metadata> <type-mapping>mySQL</type-mapping> </metadata> </local-tx-datasource> <local-tx-datasource> <jndi-name>MySqlDS2</jndi-name> <connection-url>jdbc:mysql://localhost:3306/MyPerson</connection-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <user-name>cfl</user-name> <password>123456</password> <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name> <metadata> <type-mapping>mySQL</type-mapping> </metadata> </local-tx-datasource> </datasources>

源代码下载:http://download.csdn.net/detail/chenfanglincfl/8206309

DebugLog

(javax.transaction.SystemException: java.lang.Throwable: 

Unabled to enlist resource。。。

这个毛病大致意思没法取得的资源

解决方案:把JBoss_Home/server/default/deploy下的mysql-ds.xml修改成mysql-xa-ds.xml

[com.arjuna.ats.internal.jta.transaction.arjunacore.lastResource.disallow]Adding multiple last resources is disallowed. 

这个毛病是没法配置多个数据员支持。也就是JTA在访问1个数据源是没有任何问题,但是在配置两个数据源时就出现了问题。

解决方案:

/server/default/conf文件夹中jbossjta-properties.xml文件里    <propertiesdepends="arjuna" name="jta">下面增加子节点<propertyname="com.arjuna.ats.jta.allowMultipleLastResources"value="true"/>

Incorrect columnspecifier for column 'addressId'

这个毛病也是比较常见的,是由于在配置自增长主键时,配置了字符串的主键,将主键配置为int或配置为uuid的生存策略便可。

 

总结

JPA这里还有触及到类似hibernate的4种状态,和这些实体状态之间是如何来切换、EntityManager管理容器的工作原理后面再继续学习和交换。

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐