Я работаю над проектом, где я использую главным образом EJB и JPA, но у меня проблема с ConstraintViolationException, которого не должно было случиться.JPA пакетная вставка, вызывающая ConstraintViolationException
Прежде всего у меня есть MyEntity
класс с @Id и несколькими уникальными полями. У меня есть @Stateless MyEntityRepository
класс с методом find()
, который просто возвращает MyEntity (или null), вызывая метод EntityManager get(). Другого @Stateless боба 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);
}
}
и метод 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
, который, на мой взгляд, не должен происходить, потому что я проверяю состояние MyEntityRepository.find(me) != null
перед вызовом метода persist(). Единственная идея, которая у меня есть, заключается в том, что между коммитами существует некоторая задержка, поэтому после вызова метода MyEntityRepository.find(me)
в состоянии проверки происходит коммит, и сразу после этого метод persist()
выдает исключение.
Пожалуйста, дайте мне какие-либо предложения, что читать и учиться, и как решить проблему.
Редактировать: Я обнаружил, что это проблема с поточной обработкой, поэтому, вероятно, решение имеет блокировку записи/чтения.
Действительно, это похоже на проблему синхронизации - вы выполняете операцию check-then-act в saveEntity(), а таймер mainLogicMethod() создает нити. –
Я перестала читать, когда спотыкалась о переменной me и em в том же объеме. –