jta-jpa-pessmistic-write的并发问题

时间:2018-04-09 02:40:04

标签: hibernate concurrency ejb eclipselink jta

我正在使用Glassfish v4和EJB应用程序与JPA2.1(EclipseLink)。我遇到了JTA的并发问题。基本上,我试图通过给定的名称查找实体,然后使用新的nextVal更新列。 所以EJB无状态Bean

@PersistenceContext(unitName = "db")
private EntityManager em;

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public List<Long> getWithWriteLock(final String name, final int size) {
    TypedQuery<Sequence> q = em.createNamedQuery("Example.findByName", Example.class);
    q.setParameter("name", name);
    q.setLockMode(LockModeType.PESSIMISTIC_WRITE);
    Example example = q.getSingleResult();
    final Long result = example.getNextval().longValue();
    final Long nextVal = result + size;
    final List<Long> resultList = LongStream.range(result, nextVal).boxed().collect(Collectors.toList());
    example.setNextval(BigInteger.valueOf(nextVal));
    em.merge(example);
    em.flush(); //forced flush
    return resultList;
}

应用程序部署在多个节点上,此方法通过带有WRITE锁的EJB Singleton进行评估。我们看到的是返回的列表是重复的随机时间。它甚至发生在不同的线程调用此方法甚至超过一分钟。我们已尝试使用显式刷新,合并甚至验证确实使用SELECT ... FOR UPDATE语句的SQL日志。 如果有人见过这样的话,请告诉我。

感谢。

2 个答案:

答案 0 :(得分:0)

我认为您正在使用EclipseLink的缓存。

您应该禁用此实体的缓存:

@Cacheable(false)
@Entity
public class Example {
     ...
}

另见EclipseLink/FAQ/How to disable the shared cache?

答案 1 :(得分:0)

EJB Singleton仅适用于单个jvm,在多个节点中 在环境中,您必须依赖数据库的锁定。 请勿使用REQUIRES_NEW,仅在必要时使用它。如果存在外部事务,则REQUIRES_NEW事务中的回滚事件不会影响外部事务。因为他们是不同的交易。应用程序停止外部事务并开始并提交或回滚内部事务,然后恢复外部事务。