本文部分内容节选自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
347

被折叠的 条评论
为什么被折叠?



