【问题标题】:Using different entity managers in different EJBs within the same single transaction在同一个事务中的不同 EJB 中使用不同的实体管理器
【发布时间】:2015-10-28 16:30:00
【问题描述】:
Employee employee = entityManager.find(Employee.class, 1L);

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

由于EntityManager#find()返回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) 返回 true,即返回的 Department 实体由两个 EJB 中的 EntityManagers 管理。

虽然是意料之中,但entityManager.contains(managedDepartment)如何返回true?

是否是相同的EntityManager 实例使用相同的EntityManagerFactory

【问题讨论】:

  • 像 EJB 一样,它们也是代理(指与当前事务关联的代理)

标签: hibernate jpa ejb eclipselink entitymanager


【解决方案1】:

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

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

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

但我不会将其作为您应用服务器未来版本的保证。

如果您想要一个新的持久性上下文,您可以开始一个新事务或从注入的EntityManagerFactory 手动创建一个EntityManager 实例。

出于性能考虑,我不想在您的情况下使用新的持久性上下文。

编辑:添加来自official JavaEE 7 Tutorial 的引用,解释/证明刚才所说的内容

持久化上下文会自动与当前的 JTA 事务和 EntityManager 映射到 相同的持久性单元提供对内部持久性上下文的访问 该交易。通过自动传播持久性 上下文,应用程序组件不需要将引用传递给 EntityManager 实例相互连接,以便在其中进行更改 单笔交易。 Java EE 容器管理 容器管理的实体管理器。

【讨论】:

    猜你喜欢
    • 2012-02-18
    • 1970-01-01
    • 2012-03-08
    • 2012-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-28
    • 2011-05-25
    相关资源
    最近更新 更多