在多线程程序中处理更新hibernate

时间:2013-07-11 14:42:39

标签: java multithreading hibernate

我在多线程程序中运行以下代码并获得异常: -

  

org.hibernate.exception.ConstraintViolationException:错误:重复   键值违反唯一约束“value_pkey”

    @Stateless
    @TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRED)
    public class GetHelloBean{
    @PersistenceContext(unitName = "test-unit")
        private EntityManager entityManager;

    public Hello<?> insertOrUpdateHello(Hello<?> value) {
        Hello<?> existing = null;
        try {
             existing = this.entityManager.find(Hello.class,
                    value.getKey());
            if (existing != null) {
                value = this.entityManager.merge(value);
            } else {
                this.entityManager.persist(value);
            }
            this.entityManager.flush();
        } catch (Exception e) {
            this.logger.error(" value not saved : " + value.toString()
                    + " of class  " + value.getClass() + ":" + e.getMessage());
        }

        //      

        return value;
    }

}

有人可以解释为什么以及如何处理这个问题?

1 个答案:

答案 0 :(得分:0)

此错误可能是由代码中的竞争条件引起的。如果两个或多个线程尝试使用相同的密钥更新Hello实体,则它们可能都具有从find返回的null并将尝试持久保存该实体。因此,只有“最快”的线程才会成功,而其他线程则会遇到约束违规。

如果value.getKey()是Hello实体的主键,那么仅执行merge(...)就足够了。 Hibernate将检查实体是否已存在于db或缓存中,并根据具体情况执行INSERT或UPDATE。并发执行可能仍会产生意外结果(感知无序更新)。

如果它不是Hello实体的主键,则this answer可以帮助您。