Hibernate: длинная транзакция только для чтения теперь потребует небольшого обновления БД в середине - PullRequest
0 голосов
/ 17 февраля 2011

Я написал довольно сложный механизм, который перемещается вверх и вниз по большой серии объектов, считываемых из базы данных.

Итак, у меня есть код, который выглядит примерно так:

public void go(long id) {
    try {
        beginTransaction();
        Foo foo = someDao.find(id);
        anotherObject.doSomething(foo);
        commitTransaction();
    } catch (Exception e) {
        rollbackTransaction();
    }
}

Код в doSomething (...) будет вызывать методы для получения дочерних объектов Foo и передачи этих дочерних объектов другим классам и т. Д.

До моей проблемы это была просто длинная транзакция только для чтения. Однако теперь, где-то в середине всего этого, должно быть обновление базы данных. Важно, чтобы это обновление было зафиксировано сразу. Поскольку Hibernate не поддерживает вложенные транзакции, как бы я справился с такой ситуацией, чтобы позволить мне продолжать передавать свой объект и по-прежнему вызывать методы getter для доступа к дочерним элементам, пока выполняется обновление этого базы данных?

Я думал об удалении длительной транзакции и наличии небольших транзакций повсюду. К сожалению, мой код в данный момент пропускает Foo и другие дочерние объекты везде, предполагая, что он все еще привязан к сеансу. Если это мое единственное решение, будет ли это означать, что я буду в конечном итоге получать ужасные вызовы слияния везде, чтобы просто повторно присоединиться к сеансу, чтобы методы получения работали снова? Я уверен, что должно быть более элегантное решение.

Ответы [ 3 ]

0 голосов
/ 17 февраля 2011

Если вы должны придерживаться Hibernate (и не можете рассмотреть доступ к базовому драйверу JDBC, Spring Transactions или JTA), вы, вероятно, можете просто создать поток, чтобы выполнить обновление, и заставить основной поток ждать, пока это не будет сделано (Thread.join ( )).

0 голосов
/ 18 февраля 2011

Я укусил пулю, и я считаю, что лучше разделить большую транзакцию на более мелкие транзакции, чтобы иметь большую атомарность. Это потребовало некоторой ручной загрузки кода, но моя проблема с вложенными транзакциями исчезла.

0 голосов
/ 17 февраля 2011

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

В качестве альтернативы, используйте прослушиватели сущностей , чтобы указать, что нужно обновить, а затем используйтеметод EntityManager.refresh.

Это будет несколько уродливо с многопоточностью и всем, но учтите, что вы, вероятно, не хотите, чтобы транзакция «просто обновлялась» в какой-то случайный момент времени, так какво многих случаях приведет к непредсказуемым результатам, таким как прерывание циклов for и т. д.

И если это алгоритм n-уровня, есть ли способ выполнить m уровней одновременно, сохранить состояние (скажем,идентификаторы текущей области), и запустить следующую итерацию в новой транзакции?Для этого вы можете использовать один метод без транзакции, который вызывает методы EJB, которые ограничены собственной транзакцией, возвращая состояние.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...