Удаляет ли откат транзакции Hibernate объекты "session.flush ()"? - PullRequest
26 голосов
/ 28 марта 2012

Я был сбит с толку насчет transaction.rollback. Вот пример псевдокода:

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

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

Ответы [ 3 ]

31 голосов
/ 28 марта 2012

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

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

20 голосов
/ 28 марта 2012

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

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

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

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

8 голосов
/ 28 марта 2012

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

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

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

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