我正在开发一个系统来处理消息并相应地更新数据库,但我需要在层之间保持一定程度的隔离。我想到了下面这样的东西。
-
MyDao.java
:提供数据库访问的@Stateless
Bean。MyDao
使用 JPA 访问数据库,EntityManager
由@PersistenceContext
注入。 -
MyMdb.java
:侦听队列的 MDB。MyMdb
通过注射@EJB
使用MyDao
。
一次执行MyMdb.onMessage()
需要对数据库执行多次访问,包括读取和写入。
- 一方面,这让我认为
@Stateless
bean 不是MyDao
的正确选择:MyDao
中的EntityManager
实例可以通过不同的MyMdb.onMessage()
执行随机访问,导致线程相互干扰。 - 另一方面,JPA 文档说注入的
EntityManager
只是一个代理:它运行的实际持久性上下文是绑定到 JTA 事务的上下文。这样一切都应该没问题,因为即使实体管理器是"共享"的,每个MDB也会有不同的事务正在进行中,因此在安全隔离中工作。
什么是正确的方案?我错过了什么吗?
以您所描述的方式注入无状态 EJB 中的实体管理器正是您应该做的。 这种类型的注入提供了一个"容器管理的实体管理器",它是"事务范围的"。 所以在你描述的场景中。
- onMessage MDB 调用将创建一个事务
- 对无状态 Bean 的调用将发生在相同的事务上下文中,从而创建一个实体管理器,该管理器将一直存在到事务通常在 MDB 方法返回时完成。
同一 EJB 实例的特定类型的注入实体管理器不会存活,并且不会在不同的事务中重用。