После завершения транзакции мы возвращаем объект как ноль - PullRequest
0 голосов
/ 19 февраля 2020

Я работаю над кодом, который вызывает, транзакция после транзакции.

@Asynchronous
@TransactionTimeout(value = 12, unit = TimeUnit.HOURS)
public void runExport(Long id) {
    /*
    *   some stuff that takes time
    */

    em.persist(objectTest);
    manager.runAnotherTransaction(id);
}

@Asynchronous
@TransactionTimeout(value = 1, unit = TimeUnit.HOURS)
public void runCopy(Long id) {
    if(manager.isPreviousValueCommited(id)){
        //do some stuff
    }
    /*
    *   some stuff that takes time
    */

}


//other class
public void runAnotherTransaction(long id){
    //...
    superBean.runCopy(id);
}

public void isPreviousValueCommited(long id){
    //Thread.sleep(1000) if we sleep here, object wont be null
    SomeObject obj = em.find(SomeObject.class, id); //is null, 
}

Как вы можете видеть в коде, первый метод транзакции является постоянным объектом, и после этого мы вызываем другой метод через некоторый вроде manager, а вторая транзакция хочет проверить некоторые вещи на ранее зафиксированном объекте. Но, как вы, вероятно, подозреваете, он не может, потому что объект не существует в базе данных (первая транзакция не смогла сохранить его, прежде чем мы спросим db). Когда я засыпаю перед тем, как найти этот объект, все в порядке.

Этот пример кода довольно прост, и, вероятно, имеет смысл не передавать id, а сам объект (true?), Чтобы избежать этой проблемы, но У меня вопрос. Но я хотел бы выслушать другие идеи или плюсы / минусы (возможно, есть гораздо больше минусов) этого подхода к подключению транзакции, как у меня в примере.

1 Ответ

1 голос
/ 19 февраля 2020

Используя em.persist(), вы определенно не фиксируете никаких данных. И в большинстве случаев вы даже не записываете данные в базу данных.

Ваши данные автоматически передаются контейнером после вызова EJB-метода. Поэтому после runExport данные будут зафиксированы. Перед этим контейнер также будет flush данные в базу данных.

Вы можете сделать это и программно, используя em.flush(). Но опять же, это не будет фиксировать ваши данные, просто запишите их.

Если вы действительно хотите контролировать транзакцию самостоятельно, вы должны использовать @TransactionManagement(TransactionManagementType.BEAN). Интерфейс javax.transaction.UserTransaction определяет необходимые вам методы.

...