注入EntityManager VS. EntityManagerFactory的

一个很长的问题,请忍受我。

我们正在使用Spring + JPA的Web应用程序。 我的团队正在通过注入EntityManagerFactory注入到GenericDAO (基于generics的DAO,由APPFUSE提供的东西,我们不使用JpaDaosupport ),注入EntityManager 。 我们正在使用“应用程序pipe理持久性”。

反对注入EntityManagerFactory的参数是太重了,所以不需要, EntityManager做我们需要的东西。 另外,由于Spring会为每个Web请求创build一个DAO的新实例(我怀疑这个),所以不会有任何并发​​问题,因为两个线程共享相同的EntityManager实例。

注入EFM的理由是,它是一个很好的实践,总是有一个良好的工厂处理。

我不确定哪个是最好的方法,有人可以请赐教吗?

注入EntityManagerFactory与EntityManager的优点和缺点都在这里的Spring文档中详细说明,我不确定是否可以改进。

说你的问题有一些问题应该清理。

… Spring将为每个Web请求创build一个DAO的新实例…

这是不正确的。 如果你的DAO是一个Spring bean,那么它是一个单例,除非你通过bean定义中的scope属性来configuration它。 为每个请求实例化一个DAO将是疯狂的。

注入电磁场的理由是,它是一个很好的实践,总是有一个良好的工厂处理。

这个论点并不真正成立。 一般的良好做法是指一个对象应该注入最低限度的合作者来完成工作。

我正在放下我最后收集的东西。 从Spring Reference中的“在普通的JPA中实现DAO ”

虽然EntityManagerFactory实例是线程安全的,但EntityManager实例不是。 注入的JPA EntityManager的行为就像从JPA规范定义的应用服务器的JNDI环境中获取的EntityManager。 它将所有调用委托给当前的事务性EntityManager(如果有的话); 否则,它将返回到每个操作新创build的EntityManager,实际上使其线程安全。

这意味着按照JPA规范,EntityManager实例不是线程安全的,但是如果Spring处理它们,则它们是线程安全的。

如果您使用Spring,最好注入EntityManagers而不是EntityManagerFactory。

我认为这已经被很好的涵盖了,只是为了强调几点。

  • DAO,如果被Spring注入, 默认情况下是单例 。 您必须将范围明确设置为原型,以便每次都创build一个新实例。

  • 由@PersistenceContext注入的实体pipe理器是线程安全的

这就是说,我在我的multithreading应用程序中使用单例DAO时遇到了一些问题。 我最终使DAO成为一个实例bean,并解决了这个问题。 所以,虽然文档可能会说一件事,但您可能想要彻底testing您的应用程序。

跟进:

我认为我的问题的一部分是我正在使用

 @PersistenceContext(unitName = "unit", type = PersistenceContextType.EXTENDED) 

如果您使用PersistenceContextType.EXTENDED,请记住,如果我理解正确,则必须手动closures事务。 请参阅此主题了解更多信息。

另一个后续行动:

使用实例化的DAO是一个非常糟糕的主意。 DAO的每个实例都将拥有自己的持久性caching,而对其中一个caching的更改将不会被其他DAO Bean识别。 对不起,不好的build议。

我发现在我们的DAO上设置@Repository Spring注解,并让Springpipe理的EntityManager和@PersistenceContext注解注入是让所有的东西都能stream畅运行的最方便的方法。 您受益于共享EntityManager的线程安全性和exception转换。 默认情况下,共享的EntityManager将pipe理事务,如果您将来自某个pipe理器的多个DAO组合在一起。 最后你会发现你的DAO会变得贫血。