Изменения JPA в БД не записаны до завершения метода - PullRequest
2 голосов
/ 22 марта 2019

У меня есть @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, которая обновит сущность только после завершения метода. Как я могу изменить значения объекта мгновенно?

Edit:

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

1 Ответ

4 голосов
/ 22 марта 2019

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

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

...