(12) ejb学习: JPA的传播属性

来源:互联网 发布:linux服务器租用 编辑:程序博客网 时间:2024/05/16 11:19

一 为什么需要传播属性


service调用图


如上图所示 ,  service2 可能被单独调用,也有可能被service1调用 ,也有可能在其它service中调用, 因此不能使用 UserTransaction utx方式将 

service2放入service1中 , 此刻就需要用到事务传播了,假设用service1用了required,会在service1中会创建一个事务,并将该事务传到service2中,

因此service1,service2都在同一个事务中了.


二 传播属性特性以及管理

 1 Not Supportd - 不支持,如果当前有事务上下文,将挂起当前的事务

 2 Support - 支持 , 如果有事务,将使用事务,如果没有事务,将不使用事务.

 3 Required - 需要 , 如果当前有事务上下文,将使用当前的上下文的事务,

          如果没有,则创建新的事务

 4 Required New - 需要新的事务,如果当前有事务上下文,将挂起当前的事务,

     并创建新的事务去执行任务,执行完成之后,在恢复到原来的事务.

 5 Mandatory - 当前必须要有事务上下文,如果当前没有事务,将抛出异常

 6 Nerver - 当前必须不能有事务上下文,如果有事务,将抛出异常.


三 ejb中使用传播属性示例

1 项目结构

 

Student.java : 学生实体类

StudentManager.java 学生管理接口类

StudentManagerImpl.java 学生管理实现类

StudentManagerClient.java  Junit测试类,

               测试1 : testAddStudent1  没有事务,增加学生失败效果

               测试2 : testAddStudent2 有事务,增加用户成功

persistence.xml : 配置JTA的数据源

jndi.properties : 配置JNDI

client : 为JtaTest中testWithoutJta 和 testJta  提供客户端环境

            jar包有 : JBOSS_HOME/client/*.jar

2 代码

Student.java

package leaning;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;@Entitypublic class Student {@Id@GeneratedValueprivate int id;private String name;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}}
StudentManager.java

package leaning;public interface StudentManager {   public void addStudent(String name);}

StudentManagerImpl.java

package leaning;import javax.ejb.Remote;import javax.ejb.Stateless;import javax.ejb.TransactionAttribute;import javax.ejb.TransactionAttributeType;import javax.persistence.EntityManager;import javax.persistence.PersistenceContext;/** * 事务传播属性为 Supports * **/@Stateless(name="studentManager")@Remote@TransactionAttribute(TransactionAttributeType.SUPPORTS)public class StudentManagerImpl implements StudentManager {@PersistenceContext(unitName="propagation_unit")private EntityManager em;// persist 需要事务支持public void addStudent(String name) {Student s = new Student();s.setName(name);em.persist(s);}}

StudentManagerClient.java

package test;import static org.junit.Assert.*;import javax.naming.InitialContext;import javax.transaction.UserTransaction;import leaning.StudentManager;import org.junit.Test;public class StudentManagerClient {/** * 没有事务,增加用户失败 * */@Testpublic void testAddStudent1() {try{InitialContext context = new InitialContext();StudentManager studentManager = (StudentManager)context.lookup("studentManager/remote");// 服务器端使用了事务传播特性为SUPPORTS即支持事务,如果没有事务,将不使用事务// 现在客户端没有事务,但服务端执行更新又必须要有事务支持,所以本次操作将抛出异常,无法执行studentManager.addStudent("张三");}catch(Exception e){e.printStackTrace();}}/** * 有事务,增加用户成功 * */@Testpublic void testAddStudent2() {try{InitialContext context = new InitialContext();StudentManager studentManager = (StudentManager)context.lookup("studentManager/remote");//JTA事物管理接口UserTransaction utx = (UserTransaction)context.lookup("UserTransaction");try{utx.begin(); //开启事物  studentManager.addStudent("张三");utx.commit(); //提交事物}catch(Exception e){utx.rollback();e.printStackTrace();}}catch(Exception e){e.printStackTrace();}}}
jndi.properties

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactoryjava.naming.provider.url=localhostjava.naming.factory.url.pkgs=org.jboss.naming\:org.jnp.interfaces


persistence.xml

<?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">     <!-- 采集JTA事物 --><persistence-unit name="propagation_unit" transaction-type="JTA">  <jta-data-source>java:/MySqlDS</jta-data-source>  <properties><property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" /><property name="hibernate.hbm2ddl.auto" value="update"/></properties></persistence-unit>  </persistence>



0 0
原创粉丝点击