我正在处理主要使用EJB和JPA的项目,但是我遇到了不应该发生的ConstraintViolationException问题。
首先,我有MyEntity
类与@Id和几个独特的字段。
我有@Stateless MyEntityRepository
类和find()
方法,只需通过调用EntityManager get()方法返回MyEntity(或null)。
另一个@Stateless bean是SaveEntityBean
:
@Stateless
public class SaveEntityBean {
@Inject
EntityManager em;
@Inject
MyEntityRepository repository;
public void saveEntity(MyEntity me) {
if(repository.find(me) == null) {
//the place with ConstraintViolationException
em.persist(me);
}
}
public void saveEntities(List<...> entities) {
for(MyEntity me: entities)
saveEntity(e);
}
}
并从另一个bean调用方法saveEntities(List<...> entities)
:
@Stateless
@Startup
public class SaveEntityBean {
@Inject
SaveEntityBean saveBean;
//...
@Schedule(hour = "*", minute = "*", second="*/5")
@AccessTimeout(unit = TimeUnit.MINUTES, value = 1)
public void mainLogicMethod() {
List<MyEntity> entities = io.calculateAndGetEntities();
saveBean.saveEntities(entities);
}
}
其中io.calculateAndGetEntities()
方法是长IO工作。问题是有时候我会得到org.hibernate.exception.ConstraintViolationException
,我觉得不应该这样,因为我在调用persist()方法之前检查MyEntityRepository.find(me) != null
条件。
我唯一的想法是提交之间有一些延迟,所以在条件检查中调用MyEntityRepository.find(me)
方法后,提交就会发生,然后persist()
方法抛出异常。
请给我任何建议,阅读和学习以及如何解决问题。
编辑: 我发现这是一个线程问题,因此解决方案可能是锁定写/读。
答案 0 :(得分:0)
好吧,通常在高并发环境中,解决这个问题真的很难,只是锁定不起作用(你不想使用表锁)。现在我使用来自@SQLInsert
的Hibernate org.hibernate.annotations.SQLInsert
注释,所以我的实体看起来像这样:
@SQLInsert(sql = "INSERT INTO my_entity_table(a, b, c) VALUES(?, ?, ?) ON DUPLICATE KEY UPDATE a=a;")
public class MyEntity implements Serializable {...}
当然,当您想向用户显示一些错误消息时,它会有问题,但在我的情况下它已经足够了。 据我所知,只有MySQL支持这种SQL语句,在其他RDBMS中你应该使用不同的方法。