Изменения JPA в базе данных, не записанные до завершения метода

#java #jpa #jakarta-ee #java-ee-7

#java #jpa #джакарта-ee #java-ee-7

Вопрос:

У меня есть @Stateless -Bean, который выполняет некоторые операции с базой данных одним методом

 public void doOperation(){
    User u1 = createNewUser()
    User u2 = createNewUser()
    User updated = mergeUser(u1,u2) // just as an example
    // should write to database now! 
    otherBlockingOperation()
}
  

Однако изменения не видны в базе данных до завершения операции блокировки и, следовательно, не видны во внешнем интерфейсе.

Я думал, это потому, что транзакция не зафиксирована до otherBlockingOperation() завершения. Затем я завернул otherBlockingOperation() в поток, который снова не сработал.

Однако я думаю, что реальная проблема заключается в том, merge что обновит объект только после завершения метода. Как я могу мгновенно изменить значения объекта?

Редактировать:

 @PersistanceContext
private EntityManager em;
mergeUser(T entity){
    em.merge(entity);
    em.flush();
}
  

Комментарии:

1. Пожалуйста, предоставьте код mergeUser , это может иметь отношение к делу. Вы правы в своем наблюдении о транзакциях: в @Stateless компоненте транзакция запускается (по умолчанию), а база данных обновляется только после фиксации транзакции. Даже если вы entityManager.flush() во время транзакции обновите базу данных, но все равно изменения будут видны только в вашей транзакции (если не используется какой-либо нестандартный уровень изоляции)

2. Кроме того, управление вашими собственными потоками в приложении JavaEE является основным «нет-нет». Сервер приложений должен быть единственным ответственным за обработку потоков, используя методологию JavaEE (т. е. @Asynchronous бизнес-методы и т.д.)

Ответ №1:

В зависимости от реальных бизнес-требований возможным решением было бы переместить otherBlockingOperation() метод в новый @Stateless компонент и пометить метод как @Asynchronous @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) . Это позволит эффективно запустить метод в новом потоке и новой транзакции. Вы бы просто @Inject создали новый компонент и вызвали otherBlockingOperation() метод.

Новая транзакция может быть (или не может быть) допустимой опцией, в зависимости от потребностей бизнеса (т. Е. Новая транзакция может завершиться неудачей, в то время как исходная транзакция может завершиться успешно). Однако обновление будет зафиксировано в базе данных раньше (но все равно после фиксации исходной транзакции) без зависимости от otherBlockingOperation() процесса (или даже успешной фиксации).