JPA:解读后写入的竞争条件

时间:2017-03-28 08:46:46

标签: java hibernate jpa jta java-persistence-api

我想用哈希存储唯一的实体。实体由生成的id和散列值组成,该值必须是唯一的。 我用这段代码做到了这一点:

@Stateless
@LocalBean
public class srvcEntity {

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

    private Long save(byte[hash]) {
        List<Entity> list = Entity.findByHash(hash, em); // using TypedQuery.getResultList()
        if (list != null && list.size() > 0) {
            entityId = list.get(0).getId();
        } else {
            Entity e = Entity.save(hash, em); // using em.persist()
            if (e != null) {
                entityId = e.getId();
            }
        }
        return entityId;
    }
}

这很有效,直到我有很多实体同时存储。然后竞争条件可以导致在读取时没有找到具有给定散列的实体但是在保存时我得到重复散列的ConstraintViolationException的引用。

因为我的代码存在于基于容器的事务的bean中,所以在保存失败后我根本无法再读。

如何解决这种竞争条件?

2 个答案:

答案 0 :(得分:0)

直接的方法是捕获异常,然后再次执行读取。

您还可以使用striped lock来阻止竞争条件。这在您不希望执行某些操作可能两次的情况下非常有用,但它也涉及锁定(尽管Guava Striped类允许您配置锁的数量,因此可以很好地配置吞吐量)。

答案 1 :(得分:0)

EJB方法是同步的。如果您只运行应用程序的一个实例(它不是聚集的!)那么

@Singleton

可能会解决此问题,因为此代码应该只有一个入口点可以消除竞争条件的可能性。