在同一个事务中的不同 EJB 中使用不同的实体管理器

Using different entity managers in different EJBs within the same single transaction

Employee employee = entityManager.find(Employee.class, 1L);

if (employee == null) {
    throw new EntityNotFoundException();
}

由于EntityManager#find() returns null万一,所述实体不可用,如上所示的条件测试是必要的,以避免可能的java.lang.NullPointerException否则可能。在任何地方重复这个琐碎的条件测试几乎是不可接受和不鼓励的,这使得业务逻辑应该尽可能简单,几乎不可读。

为了防止这种条件检查到处重复,我在单独的 EJB 中有一个通用方法,就像这样,

@Stateless
public class EntityManagerUtils implements EntityManagerService {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public <T extends Object> T find(Class<T> entityClass, Object primaryKey) {
        T entity = entityManager.find(entityClass, primaryKey);

        if (entity == null) {
            throw new EntityNotFoundException();
        }

        return entity;
    }
}

从另一个 EJB 内部调用此方法,如下所示,

@Stateless
public class TestBean implements TestBeanService {

    @PersistenceContext
    private EntityManager entityManager;

    @Inject
    private EntityManagerService entityManagerService;

    @Override
    public void test(Employee employee) {
        Department managedDepartment = entityManagerService.find(Department.class, employee.getDepartment().getDepartmentId());
        System.out.println("contains : " + entityManager.contains(managedDepartment));
    }
}

在这里,尽管所有事情都发生在同一笔交易中,但 entityManager.contains(managedDepartment) returns true 即 returned Department 实体是由两个 EJB 中的两个 EntityManager 管理。

虽然是预料之中的,但是entityManager.contains(managedDepartment) return怎么会是真的呢?

是否是使用相同EntityManagerFactory的同一个EntityManager实例?

我怀疑 EJB 规范是否保证 EntityManager Java 实例相同,但它保证它们由相同的 Persistence Context(同一组托管实体)支持),因为您处于同一个 JTA 事务中,并且 EntityManagers 都是由同一持久性单元(在您的情况下为默认值)管理的容器。

如果要检查环境中的实例是否相同,请检查

的输出
System.out.println("EntityManager : " + entityManager);

但我不会依赖它作为您的应用程序服务器未来版本的保证。

如果您想要一个新的持久性上下文,您可以开始一个新的事务或从注入的 EntityManagerFactory.

手动创建一个 EntityManager 实例

出于性能方面的考虑,我不想在您的情况下使用新的 Persistence Context。

编辑: 添加来自 official JavaEE 7 Tutorial 的引述 explains/justify 刚才所说的内容

The persistence context is automatically propagated with the current JTA transaction, and EntityManager references that are mapped to the same persistence unit provide access to the persistence context within that transaction. By automatically propagating the persistence context, application components don't need to pass references to EntityManager instances to each other in order to make changes within a single transaction. The Java EE container manages the lifecycle of container-managed entity managers.