在我的应用程序是群集时,是否需要调用JPA flush来检查数据库约束?

时间:2017-04-05 18:17:31

标签: java jpa concurrency ejb

我读了JPA caches SQL instructions以提高效果:

  

像Hibernate这样的JPA提供程序可以缓存它们的SQL指令   应该发送到数据库,通常直到你实际提交   交易。例如,你调用em.persist(),Hibernate记得   它必须使数据库INSERT,但实际上不执行   直到你提交交易为止。

我将一个Java EE 6应用程序部署到具有两个实例的Glassfish集群。在应用程序中存在竞争条件,其中两个单身人员执行一些昂贵的查询,然后将结果缓存在数据库表中。他们正在做同样的工作,并试图写相同的记录,所以我有时会得到一个例外:

java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (SOMESCHEMA.SOMETABLE_PK) violated

我认为最简单的方法是捕捉并忽略异常:

// In a EJB with container-managed transactions.
public Entity getExpensiveEntity(int entityId) {
    Entity entity = entityManager.find(Entity.class, entityId);
    if (entity == null) {
        try {
            result = expensiveQueries();
            entityManager.persist(result);
            entityManager.flush();
        } catch (SQLIntegrityConstraintViolationException ex) {
            // The other instance already created the result, so get it.
            result = jpa.find(result.getId());
        }
    }
    return result;
}

我认为调用flush是必要的,否则SQLIntegrityConstraintViolationException将不会发生,直到事务在EJB调用堆栈的某个地方结束,过去捕获和忽略。我是否正确,这是flush的有效用例吗?有没有更好的方法来解决这个问题?

参考

0 个答案:

没有答案