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

你可能感兴趣的:(apache,openejb)