Использование Hibernate в среде сервлетов - PullRequest
0 голосов
/ 28 июля 2010

Я пытаюсь создать объект домена, который содержит объекты только для чтения, но я могу изменить, на какие объекты он указывает.

Так что в приведенном ниже примере я бы хотел, чтобы Hibernate обрабатывал заполнениеобъекты Account и Category, но я не хочу обновлять эти объекты.Однако я могу изменить учетную запись или категорию, на которую я хочу указать расходы.

Другими словами, мне может потребоваться обновить account_id или category_id в таблице расходов, но я никогда не хочу обновлять учетную запись или категориютаблица с изменениями, которые я внес в объекты Account или Category, содержащиеся в объекте Expense.

@Entity
@Table(name = "expense")
public class Expense {

  @Id
  @GeneratedValue
  private long id;

  private String name;

  private BigDecimal amount;

  @OneToOne
  @JoinColumn(name = "id", referencedColumnName = "category_id")
  //From table called category
  private Category category;

  @OneToOne
  @JoinColumn(name = "id", referencedColumnName = "account_id")
  //From table called account
  private Account account;

Я полностью использую Hibernate или это просто не тот инструмент?Должен ли я определять свой собственный sql с помощью @SQLUpdate и @SQLInsert?

Общий поток приложения - это стандартные вещи веб-приложения.

  1. Загрузка данных из базы данных
  2. Показать в форме
  3. Собрать изменения, сделанные пользователем
  4. Сохранить эти изменения

Спасибо

1 Ответ

1 голос
/ 28 июля 2010

Это немного отклонение от цели гибернации. Изменения в постоянных объектах, как предполагается, являются постоянными. Не меняйте их, если вы не хотите, чтобы их состояние было сохранено! Объяснение и, следовательно, лучшее понимание для себя, почему вы хотите, чтобы такое поведение могло помочь вам найти решение (или помочь нам помочь вам.)

Один из вариантов, который у вас есть, - это отсоединить / высвободить сопоставленные объекты, которые вы не хотите изменять внутри слоя доступа к данным, перед возвратом объекта Expense. Тогда, пока не включено каскадирование, сделанные в них изменения не будут сохранены. ИМО это приводит к «удивительному» поведению других программистов.

Другой вариант - использовать режим гибернации без использования сеансов. Каждый вызов - это собственная операция с атомарной базой данных, и все объекты отсоединяются после возврата. Тогда только объекты, для которых вы явно вызываете saveOrUpdate, будут сохранены в базе данных. Вы можете узнать, как настроить Hibernate для работы таким образом, в справочных документах Hibernate, хотя, опять же, я не знаю, зачем вам это нужно, если вы не пытаетесь эмулировать поведение какой-то устаревшей системы, которую вы поднимаете.

И последнее замечание: с помощью сеанса категория, которую вы получите, вызвав cost.getCategory (), обычно будет тем же реальным объектом, который вы получите, вызвав session.get (Category.class, 123). Поэтому, если оба способа доступа к нему доступны внутри одного и того же сеанса, будет легко потерять отслеживание состояния его сущности, если вы попытаетесь управлять им вручную.


редактирование:

Ах-ха! Теперь это имеет больше смысла.

Если вы работаете исключительно с веб-формами CRUDy, вам не о чем беспокоиться. Пока у вас нет каскадирования, при объединении отсоединенного объекта Expense изменения в Category и Account не окажутся в базе данных. Вы можете обнулить все остальные поля, и пока идентификатор остается, все в порядке. (Предполагая, что у вас нет других вещей, таких как каскадная валидация, которая оплакивала бы это.)

Есть несколько основных шаблонов, чтобы справиться с этим немного лучше.

Один из них - поместить объект Expense в веб-сеанс пользователя. Таким образом, у вас есть все, и вашей инфраструктуре привязки веб-данных нужно только привязать к ней поля, которые фактически изменены формой. Оригинальные Category и Account все еще там (или их прокси), и скоросшиватель не должен их портить. Недостатком является, конечно, добавление состояния на стороне сервера, а также необходимость его очистки.

Второе - зарегистрировать связыватели данных, которые фактически попадают в базу данных, и получать сопоставленную сущность во время веб-привязки. Таким образом, все, что на самом деле будет отображаться в форме, это идентификатор сопоставленного поля, и механизм связывания будет извлекать и помещать туда полный объект для вас. Обратной стороной, возможно, являются ненужные обращения к базе данных, но агрессивное кэширование L2 может это исправить (при условии, что категории почти никогда не меняются, а учетные записи изменяются редко).

Возможно, вы также захотите взглянуть на шаблоны OpenSessionInView / OpenEntityManagerInView, если в настоящее время вы используете hibernate по существу без сеансов, создавая и удаляя сеансы в DAO.

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