JPA Hibernate каскадирование "многие ко многим"

Я использую JPA 2.0 и спящий режим. У меня есть класс пользователя и класс группы следующим образом:

public class User implements Serializable {
    @Id
    @Column(name="USER_ID")
    private String userId;

    @ManyToMany
    @JoinTable(name = "USER_GROUP",
               joinColumns = {
                   @JoinColumn(name = "GROUP_ID")
               },
               inverseJoinColumns = {
                   @JoinColumn(name = "USER_ID")
               }
    )
    private Set<Group> groupList;

    //get set methods
}

public class Group
{
    @Id
    @Column(name="GROUP_ID")
    private String groupId;

    @ManyToMany(mappedBy="groupList")
    private Set<User> memberList;
    //get set methods
}

Затем я создаю пользователя и группу, а затем назначаю пользователя группе.

Я хочу, чтобы когда я удаляю группу, группа будет удалена (конечно), и все отношения между пользователем и группой, которые имеет группа, будут автоматически удалены из таблицы соединения USER_GROUP, но сам пользователь не будет удален из Таблица USER.

С приведенным выше кодом при удалении группы будет удалена только строка в таблице GROUP, и у пользователя все еще будет запись в удаленной группе в таблице соединения USER_GROUP.

Если я добавлю каскад в класс User следующим образом:

@ManyToMany(cascade=CascadeType.ALL)
@JoinTable(name = "USER_GROUP",
joinColumns =
{
    @JoinColumn(name = "GROUP_ID")
},
inverseJoinColumns =
{
    @JoinColumn(name = "USER_ID")
})
private Set<Group> groupList;

Когда я удалю группу, будет удален и пользователь!

Есть ли способ добиться того, чего я хочу?


person Hery    schedule 08.02.2011    source источник


Ответы (4)


В соответствии с вашим отображением User является управляющей стороной отношения, поэтому он будет отвечать за обновление таблицы соединения.

Измените отображение JoinTable с User на Group и сделайте свойство groupList для User так, чтобы оно имело атрибут mappedBy. Это изменит группу на управляющую сторону отношения и сделает вызовы сохранения / обновления в группу, управляющую таблицей соединения.

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

person digitaljoel    schedule 08.02.2011
comment
Хммм, если я сделаю так, как вы говорите (я предполагаю, что никакого каскадирования не будет, поскольку вы ничего не упоминаете), когда у меня есть пользователь, назначенный определенной группе, что произойдет, когда я удалю пользователя? Будет ли удалена связь между пользователем и группой в таблице объединения? Будет ли удалена сама группа? - person Hery; 09.02.2011
comment
если вы сделаете это так, как я сказал, отношения между пользователем и группой будут полностью управляться со стороны группы. Это означает, что вы, вероятно, вообще не сможете удалить пользователя, пока не удалите его из всех групп. Чтобы это закрепилось, вам нужно будет удалить пользователя из группы, а затем сохранить группу. Удаление только пользователя не приведет к удалению ни отношения пользователь-группа, ни таблицы соединения. Без каскада при удалении группы будут удалены ассоциации, но не пользователи, как вы сказали в исходном вопросе. - person digitaljoel; 09.02.2011
comment
Понятно ... Итак, я должен использовать группу в качестве управляющей стороны ... Есть ли способ сделать так, чтобы обе стороны были управляющей группой? Другими словами, когда я удаляю пользователя, пользователь и группа пользователей также удаляются, но не группа, и когда я удаляю группу, группа и группа пользователей будут удалены, но не пользователь. - person Hery; 10.02.2011
comment
Продолжение предыдущего комментария. Или доступен только жесткий способ, то есть, если группа является управляющей стороной, для удаления пользователя я должен использовать объекты группы, чтобы сначала удалить пользователя, сохранить объекты группы и, наконец, удалить пользователя? - person Hery; 10.02.2011
comment
только одна сторона может быть управляющей стороной любых двусторонних отношений. Я стараюсь избегать двусторонних отношений, потому что поддерживать их может быть сложно. Лучше всего сопоставить его со стороной, которая соответствует вашему наиболее регулярному варианту использования, а затем обернуть операцию в метод обслуживания, который позаботится о том, чтобы все происходило так, как должно, например, обновление неуправляющей стороны отношений и т. Д. . - person digitaljoel; 10.02.2011
comment
Понятно ... Спасибо за предложение! - person Hery; 10.02.2011

Как уже указывалось, сделайте группу владельцем отношения, если вам не нужно каскадировать со стороны пользователя.

Затем попробуйте использовать cascade=CascadeType.MERGE, чтобы не удалять пользователя каскадно при удалении группы.

person atidafi    schedule 18.02.2011

Взгляд на проблему под другим углом:

Вы можете добавить ограничения FK в свою таблицу сопоставления "многие-ко-многим". На самом деле вы всегда должны иметь FK в своей БД по соображениям целостности данных. В этом случае, например, по крайней мере, пользователь не может быть удален, при этом оставаясь без уведомления пустыми строками в таблице сопоставления.

Если у вас есть FK, вы можете указать на удалить каскадное ссылочное действие для ограничений, и БД будет управлять автоматическим удалением таблицы сопоставления, но не объекта, как вы просили.

person Pierre Henry    schedule 01.08.2011

Вы можете сделать что-то вроде этого

@PreRemove
private void removeMembers() {
    this.memberList.clear();
}
person Vicenzo Martinelli    schedule 05.06.2019