2012-03-28 2 views
21

Я смущен насчет transaction.rollback. Вот пример псевдокода:Откат транзакции Hibernate удаляет «session.flush()» объекты?

transaction = session.beginTransaction()  
EntityA a = new EntityA();  
session.save(a);  
session.flush();  
transaction.rollback(); 

Что происходит, когда этот код работает? Есть ли у меня объект в базе данных или нет?

ответ

24

Короткий ответ: Нет, у вас не будет объекта в базе данных.

Более длинный ответ: hibernate достаточно умен, чтобы не отправлять вставки/обновления в БД до тех пор, пока он не узнает, будет ли транзакция выполнена или откат (хотя это поведение можно изменить, установив другой FlushMode), в вашем случай, вызвав флеш, вы вынуждаете SQL быть отправленным в БД, но у вас все еще есть транзакция DB, чтобы защитить вас, когда вы вызываете rollback, транзакция DB будет отброшена, удалив изменения, выполненные внутри себя, и, следовательно, ничто не будет фактически сохранено , Обратите внимание, что в зависимости от настроенного уровня изоляции транзакций другие транзакции смогут каким-то образом увидеть EntityA, который вы сохранили за короткое время между сохранением и откатом. Также обратите внимание, что флеш вызывается автоматически при попытке чтения из БД, в 99% случаев его явное указание не требуется. Единственное исключение, которое приходит на ум, - это модульное тестирование с автоматическими откатными тестами.

+0

Я не мог думать о транзакции спящего режима, напоминающей реальную транзакцию БД каким-то образом. Спасибо ! можете ли вы проверить этот вопрос? которые позволяют мне задать этот вопрос, на который вы ответили. http://stackoverflow.com/questions/9903872/hibernate-session-save-creating-not-neccessary-insert-statements – kommradHomer

+1

Эта часть ответа неверна: «hibernate достаточно умен, чтобы не отправлять вставки/обновления в DB, пока не узнает, будет ли транзакция выполнена или откат ».Hibernate будет отправлять вставки/обновления в БД всякий раз, когда сеанс очищается, и это может быть до того, как он узнает, должна ли транзакция быть выполнена или откат. – SteveT

+0

@SteveT знаете ли вы какой-либо сценарий, когда сеанс будет очищен без вызова .flush() или совершения транзакции? – ilcavero

19

Когда вы вызываете session.save(a) Hibernate в основном помнит где-то внутри сеанса, что этот объект должен быть сохранен. Он может решить, хочет ли он немедленно выпустить INSERT INTO..., спустя некоторое время или совершить фиксацию. Это улучшение производительности, позволяющее Hibernate выполнять пакетные вставки или избегать их, если транзакция отменяется.

Когда вы вызываете session.flush(), Hibernate вынужден выдать INSERT INTO... против базы данных. Сущность хранится в базе данных, но еще не совершена. В зависимости от уровня изоляции транзакции он не будет отображаться другими работающими транзакциями. Но теперь база данных знает о записи.

Когда вы звоните transaction.rollback(), Hibernate свертывает транзакцию базы данных. База данных обрабатывает откат, таким образом удаляя вновь созданный объект.

Теперь рассмотрим сценарий без flush(). Прежде всего, вы никогда не прикасаетесь к базе данных, чтобы производительность была лучше, а откат - это, в принципе, не-op. С другой стороны, если уровень изоляции транзакции равен READ UNCOMMITTED, другие транзакции могут видеть вставленную запись даже до фиксации/отката. Без flush() этого не произойдет, если Hibernate не решит flush() неявно.

+0

вы можете проверить мой другой вопрос, который заставил меня задать этот вопрос? http://stackoverflow.com/questions/9903872/hibernate-session-save-creating-not-neccessary-insert-statements – kommradHomer

7

Я думаю, вы путаете с flush и commit.

flush() синхронизирует состояние с базой данных, но не выполняет фиксацию. Состояние по-прежнему отображается по транзакции, поэтому вы можете вызвать откат для отката.

Таким образом, ответ на ваш вопрос: нет, у вас нет сущности (a) в базе данных.

+0

благодарю вас. моя основная путаница заключалась в том, чтобы не знать о реальной транзакции БД на сайте БД. – kommradHomer

Смежные вопросы