zoukankan      html  css  js  c++  java
  • EJB(四)JPA 分布式事务处理

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

     

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

     

    Ejb3.0对于分布式事务也有支持,常常和EntityManager一起使用。下面是针对多个数据源的事务管理的代码实现以及在调试过程中的一些调式日志。

     

    环境

              jboss-5.0.0.GA  jdk 1.6 

     MyEclipse

     Version:10.0

     Buildid: 10.0-20111028

    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-8"?>
    <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 

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

    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 {
    	/*
    	 * 如果只有一个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-8"?>
    
    <!-- $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在访问一个数据源是没有任何问题,但是在配置两个数据源时就出现了问题。

    解决方案:

    /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的四种状态,以及这些实体状态之间是如何来切换、EntityManager管理容器的工作原理后面再继续学习和交流。

  • 相关阅读:
    Golang Failpoint 的设计与实现
    没涉及到最值求解;观点:矩阵乘法无法表达出结果。 现实生活中事件、现象的数学表达
    多元微分学 枚举破解15位路由器密码 存储空间限制 拆分减长,求最值 数据去重
    ARP Poisoning Attack and Mitigation Techniques ARP欺骗 中间人攻击 Man-In-The-Middle (MITM) attack 嗅探 防范 Can one MAC address have two different IP addresses within the network?
    The C10K problem
    HTTP Streaming Architecture HLS 直播点播 HTTP流架构
    现代IM系统中消息推送和存储架构的实现
    现代IM系统中的消息系统架构
    长连接锁服务优化实践 C10K问题 nodejs的内部构造 limits.conf文件修改 sysctl.conf文件修改
    doubleclick cookie、动态脚本、用户画像、用户行为分析和海量数据存取 推荐词 京东 电商 信息上传 黑洞 https://blackhole.m.jd.com/getinfo
  • 原文地址:https://www.cnblogs.com/guziming/p/4232664.html
Copyright © 2011-2022 走看看