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:/My
OracleDS</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:/My
OracleDS</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管理容器的工作原理后面再继续学习和交换。