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管理容器的工作原理后面再繼續學習和交換。