EntityManager bean 的 @Autowired 与 @PersistenceContext

Posted

技术标签:

【中文标题】EntityManager bean 的 @Autowired 与 @PersistenceContext【英文标题】:@Autowired vs @PersistenceContext for EntityManager bean 【发布时间】:2015-09-28 20:59:44 【问题描述】:

有什么区别:

@Autowired
private EntityManager em;

对比:

@PersistenceContext
private EntityManager em;

这两个选项都可以在我的应用程序中使用,但我可以通过使用 @Autowired 注释来破坏某些内容吗?

【问题讨论】:

【参考方案1】:

您可以创建以下FactoryBean 以使EntityManager 可正确注入,即使是通过构造函数注入:

/**
 * Makes the @link EntityManager injectable via <i>@Autowired</i>,
 * so it can be injected with constructor injection too.
 * (<i>@PersistenceContext</i> cannot be used for constructor injection.)
 */
public static class EntityManagerInjectionFactory extends AbstractFactoryBean<EntityManager> 

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Class<?> getObjectType() 
        return EntityManager.class;
    

    @Override
    protected EntityManager createInstance() 
        return entityManager;
    


请注意,因为我们在内部使用了@PersistenceContext 注解,所以返回的EntityManager 将是一个适当的线程安全代理,因为它会通过字段注入直接在使用位置注入(使用@987654326 @)。

【讨论】:

【参考方案2】:

你不应该使用@Autowired@PersistenceContext 负责为每个线程创建一个唯一的 EntityManager。在生产应用程序中,您可以有多个客户端同时调用您的应用程序。对于每次调用,应用程序都会创建一个线程。每个线程都应该使用自己的 EntityManager。想象一下如果他们共享同一个 EntityManager 会发生什么:不同的用户将访问同一个实体。

usually the EntityManager or Session are bound to the thread (implemented as a ThreadLocal variable).

来源:https://***.com/a/42074452/2623162

EntityManager instances are not thread-safe. 

来源:https://docs.oracle.com/cd/E19798-01/821-1841/bnbqy/index.html

请注意@PersistenceContext 注解来自javax.persistence 包,而不是来自spring 框架。在 JavaEE 中,JavaEE 容器(也称为应用服务器)使用它来注入 EntityManager。 Spring 借用 PersistenceContext 注释来做同样的事情:为每个线程注入一个 application-managed(= 不是 container-managed)EntityManager bean,就像 JavaEE 容器一样。

【讨论】:

我可以在谈论线程时确认这一点。例如,如果没有 @PersistenceContext,我的应用程序会在其他线程中运行 SQL 插入/更新,但不会对数据库进行任何更改。【参考方案3】:

@PersistenceContext

返回实体管理器实例

它返回代表应用程序代码获取和释放存在上下文的容器管理代理

【讨论】:

【参考方案4】:

@PersistenceContext 允许您指定要使用的持久性单元。您的项目可能有多个数据源连接到不同的数据库,@PersistenceContext 允许您说出要操作的数据源

查看这里的解释: http://www.coderanch.com/t/481448/java-EJB-SCBCD/certification/unitName-PersistenceContext

【讨论】:

【参考方案5】:

@PersistenceContext 是为特定目的设计的JPA 标准注释。而 @Autowired 用于 Spring 中的任何依赖注入。使用 @PersistenceContext 可以让您更好地控制上下文,因为它使您能够指定可选元素,例如名称、属性

【讨论】:

这个我知道,但是对应用有什么影响呢?考虑使用 Spring 的标准 @Transactional。使用 @Autowired 时,会发生与使用 @PersistenceContext 相同的行为,并且每个应用程序事务都有 em? 我认为使用@PersistenceContext 通常是最佳实践,因为它更准确地描述了您尝试实现的依赖注入类型。此外,它还提供了专门用于 EntityManager 的可选参数,这在您拥有多个 EntityManager 时会很有用。从功能上讲,我相信您可以使用 @Autowired 实现相同的注入,但我建议您使用旨在像这样使用的注释。

以上是关于EntityManager bean 的 @Autowired 与 @PersistenceContext的主要内容,如果未能解决你的问题,请参考以下文章

没有找到 EntityManager bean?

在条件下在无状态会话 Bean 中注入特定的 EntityManager

JPA 数据存储库 - 找到 2 个 EntityManager 类型的 bean

考虑在你的配置中定义一个“javax.persistence.EntityManager”类型的bean

EntityManager bean 的 @Autowired 与 @PersistenceContext

Spring JPA/Hibernate EmptyInterceptor 不注入 Entitymanager/Spring bean