Hibernate: отношение «многие ко многим» с атрибутами: правильная конфигурация с аннотациями - PullRequest
0 голосов
/ 20 декабря 2011

У меня проблема с Hibernate (благодаря Thomas теперь проблема стала более разборчивой).

Короче говоря:

Как настроить ассоциацию ManyToMany с Hibernate, когда отношения имеют атрибут, и нам нужно сохранять, удалять и обновлять каскадно?

В целом:

Представьте себе следующую базу данных:

             User     Profile
                M______N
                     |
                     attribute

Здесь 3 таблицы:

"User", "Profile" and "User_Profile".

Теперь представьте, что User_Profile имеет 1 атрибут для отношения (и, очевидно, ключи).

Хорошо, теперь это переводится в Hibernate следующим образом:

 User:
 // The relation is Many to Many, but considering that it has an attribute, this is OneToMany with the ManyMany RelationShip
 @OneToMany(mappedBy="user", targetEntity=UserProfile.class)    
 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})
 @LazyCollection(LazyCollectionOption.TRUE)
 private Set<UserProfile> userProfile = new HashSet<UserProfile>();


 UserProfile:
 @Id    
 @ManyToOne(targetEntity=User.class,fetch=FetchType.LAZY)   
 @Cascade({CascadeType.LOCK})   
 @JoinColumns({ @JoinColumn(name="...", referencedColumnName="...") })  
 private User user; 

 @Id    
 @ManyToOne(targetEntity=Profile.class,fetch=FetchType.LAZY)    
 @Cascade({CascadeType.LOCK})   
 @JoinColumns({ @JoinColumn(name="...", referencedColumnName="...") })  
 private Profile profile;

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

 getHibernateTemplate().getSessionFactory().getCurrentSession().clear();
 getHibernateTemplate().saveOrUpdate( user );
 getHibernateTemplate().getSessionFactory().getCurrentSession().flush();

Hibernate не удаляет отношение профиля, если есть пустой набор дочерних профилей. Только добавьте профили (переопределите старые) ... Это редко ... В чем проблема?

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

1 Ответ

0 голосов
/ 20 декабря 2011

Все, что вы на самом деле делаете, это удаляете отношение и, следовательно, нет DELETE для каскада, поэтому ничего не удаляется.

Попробуйте добавить тип каскада Hibernate DELETE_ORPHAN (используя аннотацию @Cascade)чтобы Hibernate удалял сущности, на которые больше нет ссылок.

Кроме того, я бы не стал удалять только сущности Mini.Если отношения отсутствуют, т. Е. Набор Mini s пуст, обычно нет смысла сохранять SuperMini сущностей, которые теперь представляют пустую коллекцию (в редких случаях это может иметь смысл, просто подумайте, стоит линужны они вам или нет).

Редактировать :

Обратите внимание, что с DELETE_ORPHAN вы должны повторно использовать набор, иначе все отношения могут быть удалены и повторно вставлены.

В основном Hibernate будет видеть, что набор будет изменен, и выдаст удаление для «старого» набора и повторную вставку для «нового» набора.Это может потребоваться, но в случае, если вам нужно только обновление, то есть удалить только те объекты, которые больше не входят в набор, вы должны сделать следующее:

  1. очистить набор
  2. добавьте «новый» набор к повторно используемому и теперь очищенному набору, используя addAll(...)

Это должно вызвать только обновление (и удаление сирот).

...