自从JSR-220专家组在Java EE 1.5中引入基于注解的依赖注入和Java持久化API以来,就可以使用专门的@PersistenceContext和@PersistenceUnit注解分别将EntityManager或EntityManagerFactory注入到大多数Java EE组件中。
后来,我的JSR-299专家组引入了一种全新的依赖注入方法,最终被命名为“Java的上下文和依赖注入”。最初颇具争议,CDI随着时间的推移已成为Java EE平台的核心——哦,我是说,Jakarta EE——并且其他技术已采用CDI作为基础级组件模型,现在已发展到第六版。
但在CDI 1.0时代,我需要一种方法来弥合@PersistenceContext和CDI支持的@Inject注解之间的差距。而CDI本身又陷入了FUD(恐惧、不确定性和怀疑)的困境,我并没有足够的政治力量去要求EE平台小组重新定义他们当时相当新颖的依赖注入注解,以适应我们用CDI所采取的疯狂新方向。
所以我的解决方案——当时我认为非常优雅——就是让你在Java中定义映射。例如,我们可能定义以下映射
public class Databases {
@Produces @PersistenceContext(unitName="UserData")
@Users EntityManager userDatabaseEntityManager;
@Produces @PersistenceContext(unitName="DocumentData")
@Documents EntityManager docDatabaseEntityManager;
}
然后按照以下方式注入EntityManager
@Inject @Users EntityManager userDatabaseEntityManager;
@Inject @Documents EntityManager docDatabaseEntityManager;
最近,我注意到,有些人从未真正喜欢我的优雅解决方案;的确,大多数人似乎认为这是一种“黑客技巧”;而且这些人似乎不容易改变这种观点。😭
因此,我们为 Jakarta EE 11 提出了一些不同的方案。您可以在这里阅读规范。
想法是这样的:如果您只有一个持久化单元,您就可以像这样注入它的 EntityManager
或 EntityManagerFactory
@Inject EntityManager em;
@Inject EntityManagerFactory emf;
如果您有多个持久化单元,则可以使用 persistence.xml
中的新 <qualifier>
XML 元素为单元分配 CDI 标注。
<persistence-unit name="UserData">
...
<qualifier>my.program.Users</qualifier>
...
<persistence-unit name="DocumentData">
...
<qualifier>my.program.Documents</qualifier>
...
然后您可以像以前一样编写代码
@Inject @Users EntityManager userDatabaseEntityManager;
@Inject @Documents EntityManager docDatabaseEntityManager;
默认情况下,这样的注入 EntityManager
的作用域为 @TransactionScoped
。但偶尔我们希望这里更有灵活性。我们如何获得类似 JPA 扩展持久化上下文 的东西?
好的,我们还决定给你以下武器,这是一个沿着负 y 轴容易定位的武器
<persistence-unit name="UserData">
...
<qualifier>my.program.Users</qualifier>
<scope>javax.enterprise.context.RequestScoped</scope>
...
<persistence-unit name="DocumentData">
...
<qualifier>my.program.Documents</qualifier>
<scope>javax.enterprise.context.ConversationScoped</scope>
...
请理解,绝对没有任何关于 <scope> 元素存在的事情会给你权限开始共享并发执行代码之间的有状态持久化上下文。 |
显然,EntityManagerFactory
总是 @ApplicationScoped
。
新功能甚至超出了这一点:我们不仅可以注入 EntityManager
或 EntityManagerFactory
,而且为了方便,我们甚至可以使用相同的注解注入某些辅助对象:CriteriaBuilder
、PersistenceUnitUtil
、Cache
、SchemaManager
和 Metamodel
。
希望您喜欢!