Лучший способ обновить некоторые поля отсоединенного объекта в Hibernate? - PullRequest
11 голосов
/ 18 января 2010

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

public class Parent {
   int id;
   String field2;
   ...
   Child child;
}

public class Child {
   int id;
   String field3;
} 

При обновлении Parent в веб-приложении MVC я мог бы вызвать родительский экземпляр, используя Session.get (Parent.class, 123) , использовать его для заполнения формы и ее отображения. Нет DTO, только отсоединенный родительский элемент передается в представление и связывается с формой. Теперь я хочу только разрешить пользователю обновлять атрибут field2 родительского элемента. Поэтому, когда пользователь публикует форму, я получаю экземпляр Parent с заполненными id и field2 (я думаю, что здесь не имеет значения инфраструктура mvc, все ведут себя в основном одинаково при связывании).
Теперь, какую стратегию лучше всего выполнять обновление сущности? Я могу подумать о нескольких альтернативах, но я хочу услышать экспертов :) (Помните, что я не хочу терять отношения между родительским и дочерним экземплярами)

A) Снова извлеките экземпляр Parent из сеанса и замените вручную обновленные поля

Parent pojoParent; //binded with the data of the Form.
Parent entity = Session.get(Parent.class,pojoParent.getId());
entity.setField2(pojoParent.getField2()).          

Я часто этим пользуюсь. Но pojoParent, похоже, используется как секретный DTO. Также становится ужасно, если количество полей для обновления увеличивается.

B) Храните Дитя где-нибудь (httpSession?) И связывайте его последним.

Parent parent = Session.get(Parent.class,123);
//bind the retrieved parent to the form
// store the Child from parent.getChild() on the httpSession
...
//when the users submits the form...
pojoParent.setChild(someHttpSessionContext.getAttribute('Child'))
Session.save(pojoParent);

Я думаю, что это дерьмо, но я видел это в некоторых проектах ...

C) Установите отношение между Родителем и Ребенком как неизменное. Используя updatable = false в отношении, я могу обновить любое родительское поле, не беспокоясь о потере ребенка. В любом случае, это довольно ограничительно, и отношения никогда не будут обновляться.

Итак, что вы думаете, это лучший способ решить эту ситуацию?

Заранее спасибо!

Ответы [ 3 ]

10 голосов
/ 18 января 2010

После загрузки родительского объекта вы сказали

Теперь я хочу только разрешить пользователю обновлять атрибут field2 родительского элемента

В зависимости от варианта использования вы можете использовать объект UpdateableParent

public class UpdateableParent {

   private String field2;

   // getter's and setter's

}

Теперь наш родительский репозиторий

@Repository
public class ParentRepositoryImpl implements ParentRepository {

    @Autowired
    private SessionFactory sessionFactory;


    public void updateSpecificUseCase(UpdateableParent updateableParentObject) {

        Parent parent = sessionFactory.getCurrentSession().load(Parent.class, updateableParentObject.getId());

        try {
            // jakarta commons takes care of copying Updateable Parent object to Parent object

            BeanUtils.copyProperties(parent, updateableParentObject);
        } catch (Exception e) {
            throw new IllegalStateException("Error occured when updating a Parent object", e);
        }

    }

}

Его преимущества

  • Это безопасно: вы просто обновляете то, что вам действительно нужно
  • Вам не нужно беспокоиться о платформе MVC (некоторые фреймворки MVC позволяют вам устанавливать свойство allowFields). Что произойдет, если вы забудете некоторые разрешенные поля ???

Хотя это не вопрос, связанный с технологией, Seam framework позволяет обновлять только то, что вы хотите. Так что вам не нужно беспокоиться о том, какой шаблон использовать.

С уважением,

3 голосов
/ 19 января 2010

A) Извлечь родительский экземпляр из Сеанс снова и заменить вручную обновленные поля

это, похоже, самая функциональная версия, которую я использовал за последние несколько лет.

Б) Храните ребенка где-нибудь (httpSession?) и связать его последний.

Я бы посоветовал против этого, особенно если вы хотите следовать парадигме REST, которая делает состояние на стороне сервера полным нет-нет. И вы в конечном итоге будете использовать пространство кучи для отсоединенных объектов, хотя пользователь, инициировавший сеанс, ушел на кофе:)

C) Установите связь между Родителем и Ребенок как неизменный.

ИМХО, это тоже не очень хороший способ, хотя он подходит для небольшого проекта с небольшой моделью персистентности. Но даже в небольшом приложении это может привести к головной боли при попытке изменить код.

0 голосов
/ 18 января 2010

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

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