Oli*_* J. 5 java jpa entitymanager concept
我有大约10个EntityManagers的Java EE应用程序(EM的数量可能会增加).我的应用程序还包含许多无状态,有状态和消息驱动的bean.
@PersistenceContext我可能会将所有内容存储在一个单独的bean中,并使用其他bean访问它,而不是在每个bean中注入我的EM (以及两种方法来检测用户使用哪个EM).像这样,不用担心可维护性.
然而,将EM存储在一个单独的bean中是否是线程安全的?瓶颈会出现吗?
另一个解决方案是创建一个抽象类,所有bean都将扩展它.
什么是更好的解决方案?
实体管理器不应该是线程安全的,因此您不应该通过Singleton共享它们.这与为什么不应该将实体管理器注入Servlet的原因相同,以及为什么在这样的Web组件中从JNDI进行查找 - 应该随时返回实体管理器的不同实例.
在实践中,一些实现可以提供线程安全的实体管理器,因此在测试期间它似乎可行.但是,为了便于携带并保护您免受升级困难,您不应该依赖于此.
您可以在一个bean中定义所有实体管理器,而不是从公共基类继承,并在需要实体管理器的任何地方注入它.
例如
@Stateless
public class EntityManagerProviderBean {
@PersistenceContext(unitName="foo")
private EntityManager entityManagerFoo;
@PersistenceContext(unitName="bar")
private EntityManager entityManagerBar;
public EntityManager getEntityManager() {
return ...? entityManagerFoo : entityManagerBar;
}
}
Run Code Online (Sandbox Code Playgroud)
(其中......是用于选择正确的实体管理器的逻辑)
将此注入需要实体管理器的bean:
@Stateless
public class MyService {
@EJB
private EntityManagerProviderBean entityManagerProvider;
public void doStuff(MyEntity myEntity) {
entityManagerProvider.getEntityManager().update(myEntity);
}
}
Run Code Online (Sandbox Code Playgroud)
或者,以下可能更整洁:
@Stateless
@PersistenceContexts({
@PersistenceContext(unitName="foo", name = "fooENC"),
@PersistenceContext(unitName="bar", name = "barENC") }
)
public class EntityManagerProviderBean {
@Resource
private EJBContext context;
public EntityManager getEntityManager() {
return (EntityManager) context.lookup(... ? "fooENC" : "barENC");
}
}
Run Code Online (Sandbox Code Playgroud)
最后一个示例将所有持久化上下文映射到bean的ENC中,在那里可以方便地以编程方式检索它们.
不幸的是,人们忘记将后一种语法的测试添加到TCK,随后主要供应商忘记实现它(请参阅http://java.net/jira/browse/JPA_SPEC-38和https://issues.jboss.org/浏览/ AS7-5549),所以测试它是否适用于您的服务器.
容器管理的实体管理器自动随当前 JTA 事务传播,并且EntityManager映射到同一持久性单元的引用提供对该事务内持久性上下文的访问。因此,从单例中共享实体管理器并不是一个好习惯,除了并发问题之外,它还会导致在 bean 上调用的每个方法都使用相同的事务上下文。满足您的需求的一个简单解决方案是在您的 bean 中
注入引用并创建调用该方法的对象。缺点是您应该手动管理事务,而不再依赖容器。
否则,另一种方法可以将所有实体管理器注入到主企业 bean 中,并使用将适当的管理器传递给的方法在服务 bean 中实现业务逻辑。后一种解决方案的示例:EntityManagerFactoryEntityManagercreateEntityManager()
@Stateless
class MainBean {
@PersistenceContext EntityManager em1;
@PersistenceContext EntityManager em2;
...
@EJB WorkerBean1 workerBean1;
@EJB WorkerBean2 workerBean2;
...
void method1(Object param1, Object param2) {
workerBean1.method1(em1, param1, param2);
}
void method2(Object param1, Object param2, Object param3) {
workerBean2.method2(em2, param1, param2, param3);
}
...
}
@Stateless
class WorkerBean1 {
void method1(EntityManager em, Object param1, Object param2) {
...
}
...
}
@Stateless
class WorkerBean2 {
void method2(EntityManager em, Object param1, Object param2, Object param3) {
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13226 次 |
| 最近记录: |