1

我想用它们的哈希值存储唯一的实体。实体由生成的 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 中,所以在保存失败后我根本无法再次读取。

我该如何解决这种竞争状况?

4

2 回答 2

0

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

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

于 2017-03-28T09:02:23.873 回答
0

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

@单身人士

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

于 2017-03-28T09:33:58.830 回答