Это немного отклонение от цели гибернации. Изменения в постоянных объектах, как предполагается, являются постоянными. Не меняйте их, если вы не хотите, чтобы их состояние было сохранено! Объяснение и, следовательно, лучшее понимание для себя, почему вы хотите, чтобы такое поведение могло помочь вам найти решение (или помочь нам помочь вам.)
Один из вариантов, который у вас есть, - это отсоединить / высвободить сопоставленные объекты, которые вы не хотите изменять внутри слоя доступа к данным, перед возвратом объекта Expense. Тогда, пока не включено каскадирование, сделанные в них изменения не будут сохранены. ИМО это приводит к «удивительному» поведению других программистов.
Другой вариант - использовать режим гибернации без использования сеансов. Каждый вызов - это собственная операция с атомарной базой данных, и все объекты отсоединяются после возврата. Тогда только объекты, для которых вы явно вызываете saveOrUpdate, будут сохранены в базе данных. Вы можете узнать, как настроить Hibernate для работы таким образом, в справочных документах Hibernate, хотя, опять же, я не знаю, зачем вам это нужно, если вы не пытаетесь эмулировать поведение какой-то устаревшей системы, которую вы поднимаете.
И последнее замечание: с помощью сеанса категория, которую вы получите, вызвав cost.getCategory (), обычно будет тем же реальным объектом, который вы получите, вызвав session.get (Category.class, 123). Поэтому, если оба способа доступа к нему доступны внутри одного и того же сеанса, будет легко потерять отслеживание состояния его сущности, если вы попытаетесь управлять им вручную.
редактирование:
Ах-ха! Теперь это имеет больше смысла.
Если вы работаете исключительно с веб-формами CRUDy, вам не о чем беспокоиться. Пока у вас нет каскадирования, при объединении отсоединенного объекта Expense
изменения в Category
и Account
не окажутся в базе данных. Вы можете обнулить все остальные поля, и пока идентификатор остается, все в порядке. (Предполагая, что у вас нет других вещей, таких как каскадная валидация, которая оплакивала бы это.)
Есть несколько основных шаблонов, чтобы справиться с этим немного лучше.
Один из них - поместить объект Expense
в веб-сеанс пользователя. Таким образом, у вас есть все, и вашей инфраструктуре привязки веб-данных нужно только привязать к ней поля, которые фактически изменены формой. Оригинальные Category
и Account
все еще там (или их прокси), и скоросшиватель не должен их портить. Недостатком является, конечно, добавление состояния на стороне сервера, а также необходимость его очистки.
Второе - зарегистрировать связыватели данных, которые фактически попадают в базу данных, и получать сопоставленную сущность во время веб-привязки. Таким образом, все, что на самом деле будет отображаться в форме, это идентификатор сопоставленного поля, и механизм связывания будет извлекать и помещать туда полный объект для вас. Обратной стороной, возможно, являются ненужные обращения к базе данных, но агрессивное кэширование L2 может это исправить (при условии, что категории почти никогда не меняются, а учетные записи изменяются редко).
Возможно, вы также захотите взглянуть на шаблоны OpenSessionInView / OpenEntityManagerInView, если в настоящее время вы используете hibernate по существу без сеансов, создавая и удаляя сеансы в DAO.