OpenEJB (3)

本文部分内容节选自Enterprise JavaBeans 3.0 by Bill Burke & Richard Monson-Haefel

 

4 Persistence
    EJB支持声明性事务,事务传播行为可以由TransactionAttribute annotation或者XML配置文件指定。事务属性有下列可选值:NotSupported、Supports、Required、RequiresNew、Mandatory和Never(Srping多支持一个NESTED)。默认的事务属性是Required。
    伴随着事务的传播,persistence context也有特定的传播规则:

  • 如果一个EJB调用了具有不同事务范围的另一个EJB,那么persistence context不会被传播。
  • 如果在事务范围之外调用transaction scoped entity manager,会创建一个与调用时间等长的persistence context。
  • 如果在事务范围内调用transaction scoped entity manager,并且当前没有persistence context与事务关联,那么会创建一个persistence context,当事务被提交或者回滚后,persistence context也就自动结束,被EntityManager管理的所有entity都变成detached状态。
  • 如果在事务范围内调用extended entity manager,那么不论是否在事务内,entity manager在其整个生命周期内维护同一个persistence context。
  • Stateful session bean是唯一允许借助@PersistenceContext注入extended persistence context的EJB组件。当stateful session bean被移除时,extended persistence context也会被关闭。
  • 如果使用transaction scoped persistence context的EJB调用了使用extended persistence context的stateful session bean,那么会导致异常。
  • 如果使用extended persistence context的stateful session bean调用了另一个注入transaction scoped persistence context的EJB,那么extended persistence context会被传播。
  • 如果使用extended persistence context的stateful session bean调用了另一个注入extended persistence context的stateful session bean,那么extended persistence context会被传播。
  • Persistence context只是在注入本地接口时有效,如果被注入的是远程接口,则嵌套方和被嵌套方将不会共享persistence context。

    以下是个简单的例子:

import javax.ejb.Local;

@Local
public interface StatelessLocal {
	
	void doStatelessLocal(Movie m);
	
}
import javax.ejb.Remote;

@Remote
public interface StatelessRemote {
	
	void doStatelessRemote(Movie m);
	
}
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;

import com.versus.ejb.injection.entitymanager.Movie;

@Stateless
public class StatelessImpl implements StatelessLocal, StatelessRemote {
	//
	@PersistenceContext(unitName = "ejb", type = PersistenceContextType.TRANSACTION)
	private EntityManager entityManager;
	
	public void doStatelessLocal(Movie movie) {
		//
		System.out.println("in StatelessImpl.doStatelessLocal()");
		@SuppressWarnings("unused")
		Movie m2 = entityManager.find(Movie.class, new Integer(2));
		
		//
		System.out.println(entityManager.contains(movie));
	}

	public void doStatelessRemote(Movie movie) {
		//
		System.out.println("in StatelessImpl.doStatelessRemote()");
		@SuppressWarnings("unused")
		Movie m2 = entityManager.find(Movie.class, new Integer(2));
		
		//
		System.out.println(entityManager.contains(movie));
	}
}
import javax.ejb.Local;

@Local
public interface Stateful1Local {
	
	void doStatefulLocal();
	
}
import javax.ejb.Remote;

@Remote
public interface Stateful1Remote {
	
	void doStatefulRemote();
	
}
import javax.ejb.EJB;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;

@Stateful
public class Stateful1Impl implements Stateful1Local, Stateful1Remote {
	//
	@PersistenceContext(unitName = "ejb", type = PersistenceContextType.EXTENDED)
	private EntityManager entityManager;
	
	//
	@EJB
	private StatelessLocal statelessLocal;
	
	@EJB
	private StatelessRemote statelessRemote;
	
	@EJB
	private Stateful2Local stateful2Local;
	
	@EJB
	private Stateful2Remote stateful2Remote;
	
	
	public void doStatefulLocal() {
		//
		System.out.println("in Stateful1Impl.doStatefulLocal()");
		Movie m1 = entityManager.find(Movie.class, new Integer(1));
		System.out.println(entityManager.contains(m1));
        
        //
        statelessLocal.doStatelessLocal(m1);
        statelessRemote.doStatelessRemote(m1);
        
        //
        stateful2Local.doStatefulLocal(m1);
        stateful2Remote.doStatefulRemote(m1);
	}

	public void doStatefulRemote() {
		//
		System.out.println("in Stateful1Impl.doStatefulRemote()");
		Movie m1 = entityManager.find(Movie.class, new Integer(1));
		System.out.println(entityManager.contains(m1));
        
        //
        statelessLocal.doStatelessLocal(m1);
        statelessRemote.doStatelessRemote(m1);
        
        //
        stateful2Local.doStatefulLocal(m1);
        stateful2Remote.doStatefulRemote(m1);
	}
}
import javax.ejb.Local;

@Local
public interface Stateful2Local {
	
	void doStatefulLocal(Movie m);
	
}
import javax.ejb.Remote;

@Remote
public interface Stateful2Remote {
	
	void doStatefulRemote(Movie m);
	
}
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;

@Stateful
public class Stateful2Impl implements Stateful2Local, Stateful2Remote {
	//
	@PersistenceContext(unitName = "ejb", type = PersistenceContextType.EXTENDED)
	private EntityManager entityManager;
	
	public void doStatefulLocal(Movie movie) {
		//
		System.out.println("in Stateful2Impl.doStatefulLocal()");
		@SuppressWarnings("unused")
		Movie m3 = entityManager.find(Movie.class, new Integer(3));
		
		//
		System.out.println(entityManager.contains(movie));
	}

	public void doStatefulRemote(Movie movie) {
		//
		System.out.println("in Stateful2Impl.doStatefulRemote()");
		@SuppressWarnings("unused")
		Movie m3 = entityManager.find(Movie.class, new Integer(3));
		
		//
		System.out.println(entityManager.contains(movie));
	}
}
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;

public class PersistenceTest {
	
	public static void main(String args[]) throws Exception {
		//
		Properties properties = new Properties();
		properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
		InitialContext ctx = new InitialContext(properties);
		
		// 
		if(true) {
			Object ref1 = ctx.lookup("Stateful1ImplLocal");
			Stateful1Local simpleStatefulLocal = (Stateful1Local)PortableRemoteObject.narrow(ref1, Stateful1Local.class);
			simpleStatefulLocal.doStatefulLocal();
			
			Object ref2 = ctx.lookup("Stateful1ImplRemote");
			Stateful1Remote simpleStatefulRemote = (Stateful1Remote)PortableRemoteObject.narrow(ref2, Stateful1Remote.class);
			simpleStatefulRemote.doStatefulRemote();
		}
	}
}

    以上代码的输出是:
    in Stateful1Impl.doStatefulLocal()
    true
    in StatelessImpl.doStatelessLocal()
    true
    in StatelessImpl.doStatelessRemote()
    false
    in Stateful2Impl.doStatefulLocal()
    true
    in Stateful2Impl.doStatefulRemote()
    false
    in Stateful1Impl.doStatefulRemote()
    true
    in StatelessImpl.doStatelessLocal()
    true
    in StatelessImpl.doStatelessRemote()
    false
    in Stateful2Impl.doStatefulLocal()
    true
    in Stateful2Impl.doStatefulRemote()
    false

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值