#java #jhipster
#java #спящий режим #весна #транзакционное
Вопрос:
У меня есть метод, аннотированный с помощью @Transactional . Я извлекаю объект из моей базы данных Oracle, изменяю поле, а затем возвращаюсь из метода. Я забыл сохранить объект, но обнаружил, что база данных все равно обновляется.
ApplicationContext
<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
мой метод
@Transactional
public void myMethod(long id) {
MyObject myObj = dao.getMstAttributeById(id);
myObj.setName("new name");
//dao.update(myObj);
}
мой вопрос в том, почему MyObject сохраняется в базе данных?
Комментарии:
1. поскольку платформа обнаружила изменение значения объекта и сохранила его для вас
2. без вызова метода сохранения? Как я могу это предотвратить? Я даже выдал исключение, и оно все еще сохранялось?
3. Нет, если вы создадите исключение, оно не сохранится. И вы можете управлять этим, вам просто нужно прочитать документацию и научиться использовать фреймворк.
4. Джон. Как вы это решили. У меня тоже такая же проблема
Ответ №1:
Поскольку hibernate автоматически обнаружит изменения, внесенные в постоянные объекты, и соответствующим образом обновит базу данных. Это поведение описано в главе 11 справочного руководства по гибернации. Соответствующая часть гласит:
Режим гибернации определяет и поддерживает следующие состояния объекта:
Переходный — объект является переходным, если он только что был создан с использованием оператора new, и он не связан с сеансом гибернации. У него нет постоянного представления в базе данных, и значение идентификатора не было присвоено. Временные экземпляры будут уничтожены сборщиком мусора, если приложение больше не содержит ссылку. Используйте сеанс гибернации, чтобы сделать объект постоянным (и пусть гибернация позаботится о SQL-операторах, которые необходимо выполнить для этого перехода).
Постоянный — постоянный экземпляр имеет представление в базе данных и значение идентификатора. Возможно, оно просто было сохранено или загружено, однако по определению оно находится в области сеанса. Hibernate обнаружит любые изменения, внесенные в объект в постоянном состоянии, и синхронизирует состояние с базой данных по завершении единицы работы. Разработчики не выполняют инструкции обновления вручную или инструкции УДАЛЕНИЯ, когда объект должен быть сделан переходным.
Отсоединенный — отсоединенный экземпляр — это объект, который был постоянным, но его сеанс был закрыт. Конечно, ссылка на объект остается действительной, и отдельный экземпляр может быть даже изменен в этом состоянии. Отсоединенный экземпляр может быть повторно подключен к новому сеансу в более поздний момент времени, что делает его (и все модификации) снова постоянным. Эта функция позволяет использовать модель программирования для длительных операций, требующих времени на обдумывание пользователем. Мы называем их транзакциями приложения, то есть единицей работы с точки зрения пользователя.
Комментарии:
1. Это имеет смысл, но как я могу отсоединить свою сущность. Я использую запрос JPA для извлечения объекта, и мне нужно манипулировать дочерними записями для определенной операции только для чтения, чтобы я отвечал JSON, который соответствует запросу. Однако я не хочу удалять или обновлять дочерние записи, которые не относятся к этому запросу; просто замаскируйте их от пользователя.
2. @meriton, , Просто любопытно узнать, что, если это правильная практика кодирования?
3. @meriton безупречный ответ!
Ответ №2:
Если вы используете JPA, то в спецификации говорится, что если ваша сущность находится в управляемом состоянии (и это то, что вы делаете, извлекая данные из DAO в активной транзакции), все внесенные в нее изменения будут отражены в базе данных во время фиксации транзакции.
Итак, другими словами — на самом деле не имеет значения, вызываете ли вы операцию обновления или нет, потому что фиксация транзакции приведет к удалению изменений в базе данных.
Комментарии:
1. Спасибо, я искал и искал, но подумал, что у меня где-то проблема с конфигурацией. Боже, это имеет смысл и просто.
2. @Piotr, , Просто любопытно узнать, что, если это правильная практика кодирования?
Ответ №3:
Раньше я @Transactional(readOnly = true)
решал эту проблему
Комментарии:
1. @Transactional(распространение = распространение. ТРЕБУЕТСЯ, только для чтения = true) сработало для меня
Ответ №4:
Я обнаружил, что предотвращение автоматического обновления базы данных — это двухэтапный процесс.
Шаг I: :
getSession().setFlushMode(FlushMode.MANUAL) // [FlushMode.NEVER is depracated in 4.x]
Шаг II :
getSession().clear(); //This will actually discard all changes
Ответ №5:
Для JPA вызовите entityManager.detach(entity)
, чтобы избежать автоматической очистки. Но вы должны быть осведомлены о том, что отдельный объект потеряет ORM magic после, например, отложенной выборки, каскадного обновления.