我在多线程程序中运行以下代码并获得异常: -
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;
}
}
有人可以解释为什么以及如何处理这个问题?
答案 0 :(得分:0)
此错误可能是由代码中的竞争条件引起的。如果两个或多个线程尝试使用相同的密钥更新Hello实体,则它们可能都具有从find返回的null
并将尝试持久保存该实体。因此,只有“最快”的线程才会成功,而其他线程则会遇到约束违规。
如果value.getKey()
是Hello实体的主键,那么仅执行merge(...)
就足够了。 Hibernate将检查实体是否已存在于db或缓存中,并根据具体情况执行INSERT或UPDATE。并发执行可能仍会产生意外结果(感知无序更新)。
如果它不是Hello实体的主键,则this answer可以帮助您。