使用构造函数注入是最佳实践。但是我无法通过@PersistenceContext
来实现。
我想要以下构造函数:
private final EntityManager entityManager;
@Autowired
public MyService(@PersistenceContext EntityManager entityManager) {
this.entityManager = entityManager;
}
但是我不能,因为@PersistenceContext
仅适用于TYPE
,METHOD
和FIELD
。
问::如何通过构造函数注入来注入一个容器管理的 EntityManager
?
答案 0 :(得分:1)
您似乎正在使用spring,因此您的解决方案将很容易:
@Component
@Scope("prototype")
public class MyPersistenceContainer
{
@PersistenceContext
private EntityManager em;
public EntityManager getEntityManager()
{
return em;
}
}
现在您可以简单地在构造函数中注入此类的实例,它将始终持有有效的EntityManager(由于bean作用域)。提醒您:在网络环境中,您可能应该使用@SessionScope
甚至@RequestScope
而不是原型,这样可以节省资源
但是有一些要考虑的问题:
使用依赖于以下对象的单例作用域的bean时, 仅限原型,请注意依赖项是 在实例化时间解决。这意味着如果您依赖 将原型范围内的bean注入一个单一范围内的bean,一个品牌 新的原型bean将被实例化,然后注入依赖项 到单例豆中...但是仅此而已。完全一样的原型 实例将是曾经提供给的唯一实例 单身范围的bean,如果您想要的话,这很好。
但是,有时您真正想要的是单例作用域 bean能够获得一个全新的实例 在运行时,原型范围内的bean一次又一次。在那里面 情况下,仅依赖项注入一个原型作用域的bean是没有用的 放入您的Singleton bean中,因为如上所述, 当Spring容器实例化单例时发生一次 Bean并解析并注入其依赖项。如果你在 您需要获取(原型)的全新实例的场景 bean在运行时一次又一次地被引用 标题为第4.3.7节“方法注入”的部分
因此,如果要将“ entity manager container-bean”注入到Singleton bean中,(这是默认范围),请查看https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-method-injection
答案 1 :(得分:0)
使用 Spring Data 应该是可能的。但是,如果您出于某种原因不想在您的项目中使用 Spring Data(例如,您只是将遗留项目做得更好),您可以创建以下 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
将是一个适当的线程安全代理,因为它会直接在使用字段注入的地方注入.