注入EntityManager Vs. EntityManagerFactory的

SB.*_*SB. 68 java spring jpa entitymanager

一个很长的问题,请耐心等待.

我们将Spring + JPA用于Web应用程序.我的团队在讨论如何在注入EntityManagerFactoryGenericDAO(基于泛型的东西对AppFuse中提供的线DAO,我们不使用JpaDaosupport过的注射某种原因)EntityManager.我们正在使用"应用程序管理持久性".

反对注入a的论点EntityManagerFactory是它太重而且不需要,EntityManager我们需要它.此外,由于Spring会为每个Web请求创建一个DAO的新实例(我怀疑这一点),因此不会出现任何并发问题,因为同一个EntityManager实例中有两个线程共享.

注入EFM的理由是,它是一个很好的做法,总是很好地拥有工厂的句柄.

我不确定哪种方法最好,有人可以赐教吗?

ska*_*man 51

优点和注入的EntityManagerFactory VS的EntityManager的缺点在Spring文档都列明在这里,我不知道如果我能在改善.

这么说,你的问题中有一些要点应该被清除.

... Spring将为每个Web请求创建一个新的DAO实例...

这是不正确的.如果您的DAO是一个Spring bean,那么它是一个单例,除非您通过scopebean定义中的属性进行配置.为每个请求实例化DAO都会很疯狂.

注入EMF的论点是,对于工厂来说,它是一个很好的做法.

这种说法并不真正有用.一般的良好实践表明,应该向一个对象注入完成其工作所需的最少合作者.

  • 如果你不能改进他们的解释,你能解释一下吗?该文件中有很多内容,但我不完全明白它在哪里“拼写出来”。此外,最好有一个可以独立的答案,而不需要人们通过链接来查看完整的答案。 (3认同)

SB.*_*SB. 25

我正在放下我最终收集到的东西.从Spring Reference中的" 基于普通JPA实现DAO "一节:

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

这意味着根据JPA规范,EntityManager实例不是线程安全的,但如果Spring处理它们,它们将成为线程安全的.

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


Jam*_*hon 9

我认为这已经很好地涵盖了,但只是为了强调几点.

  • 如果由Spring注入,DAO 默认为单例.您必须将范围显式设置为prototype,以便每次都创建一个新实例.

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

话虽这么说,我的多线程应用程序中的单例DAO确实存在一些问题.我最终使DAO成为一个实例bean,并解决了这个问题.因此,虽然文档可能会说一件事,但您可能希望彻底测试您的应用程序.

跟进:

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

@PersistenceContext(unitName = "unit",
    type = PersistenceContextType.EXTENDED)
Run Code Online (Sandbox Code Playgroud)

如果您使用PersistenceContextType.EXTENDED,请记住,如果我理解正确,您必须手动关闭事务.有关更多信息,请参阅主题.

另一个后续行动:

使用实例化DAO是一个非常糟糕的主意.DAO的每个实例都有自己的持久性缓存,其他DAO bean无法识别对一个缓存的更改.抱歉,不好的建议.


Gaë*_*iou 6

我发现在我们的DAO上设置@Repository Spring注释并使用Spring管理的EntityManager并通过@PersistenceContext注释注入是使一切工作流畅的最方便的方法.您可以从共享EntityManager的线程安全性和异常转换中受益.默认情况下,如果您将来自管理器的多个DAO组合在一起,则共享的EntityManager将管理事务.最后你会发现你的DAO会变得贫血.