Сохранение транзакций без вызова метода обновления - PullRequest
36 голосов
/ 19 ноября 2011

У меня есть метод, аннотированный @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 сохраняется в базе данных?

Ответы [ 5 ]

56 голосов
/ 19 ноября 2011

Поскольку hibernate автоматически обнаружит изменения, внесенные в постоянные объекты, и соответствующим образом обновит базу данных. Это поведение описано в главе 11 справочного руководства по спящему режиму. Соответствующая часть гласит:

Hibernate определяет и поддерживает следующие состояния объекта:

  • Transient - объект является временным, если он только что был создан с использованием оператора new, и он не связан с Hibernate Session. Он не имеет постоянного представления в базе данных, и значение идентификатора не было назначено. Временные экземпляры будут уничтожены сборщиком мусора, если приложение больше не будет содержать ссылку. Используйте сеанс Hibernate, чтобы сделать объект постоянным (и пусть Hibernate позаботится о операторах SQL, которые необходимо выполнить для этого перехода).

  • Постоянный - постоянный экземпляр имеет представление в базе данных и значение идентификатора. Возможно, он просто был сохранен или загружен, однако по определению он входит в область действия сеанса. Hibernate обнаружит любые изменения, внесенные в объект в постоянном состоянии, и синхронизирует состояние с базой данных после завершения единицы работы. Разработчики не выполняют ручные операторы UPDATE или операторы DELETE, когда объект должен быть переходным.

  • Detached - отсоединенный экземпляр - это постоянный объект, но его Сессия была закрыта. Разумеется, ссылка на объект все еще действительна, и отсоединенный экземпляр может даже измениться в этом состоянии. Отдельный экземпляр может быть снова присоединен к новому сеансу позднее, что делает его (и все модификации) снова постоянным. Эта функция позволяет модели программирования для длительных единиц работы, которые требуют времени на обдумывание пользователем. Мы называем их прикладными транзакциями, то есть единицей работы с точки зрения пользователя.

5 голосов
/ 19 ноября 2011

Если вы используете JPA, то в спецификации сказано, что если ваша сущность находится в управляемом состоянии (и это то, что вы делаете, выбирая данные из DAO в рамках активной транзакции), все внесенные в него изменения будут отражены в базе данных во время транзакции .

Итак, другими словами - на самом деле не имеет значения , если вы вызываете операцию обновления или нет, потому что фиксация транзакции сбрасывает изменения в базе данных.

1 голос
/ 10 апреля 2014

Я обнаружил, что предотвращение автоматического обновления базы данных является двухэтапным процессом.

Шаг I::

getSession().setFlushMode(FlushMode.MANUAL) // [FlushMode.NEVER is depracated in 4.x]

Шаг II:

getSession().clear(); //This will actually discard all changes
0 голосов
/ 20 марта 2019

Для JPA, позвоните entityManager.detach(entity), чтобы избежать автоматического сброса.Но вам нужно знать, что отсоединенный объект потеряет магию ORM после, например, отложенной выборки, каскадного обновления.

0 голосов
/ 12 февраля 2019

Я использовал @Transactional(readOnly = true), чтобы решить это

...