• 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管理容器的工作原理后面再继续学习和交流。

  • 相关阅读:
    代码阅读之术一:结构与源流
    linux cat /etc/passwd 说明
    Linux软连接
    文件上传文件的权限--lnmp 环境配置,尤其整个项目复制过来
    Redis面试总结
    php上传文件与图片到七牛的实例详解
    在浏览器中打开php文件时,是Linux中的哪个用户执行的?
    Laravel [1045] 解决方法 Access denied for user 'homestead'@'localhost'
    linux中快速清空文件内容的几种方法
    linux如何查看所有的用户和组信息?
  • 原文地址:https://www.cnblogs.com/guziming/p/4232664.html
Copyright © 2020-2023  润新知