Как избежать удаления дочерней (не принадлежащей стороне) сущности с помощью Hibernate (без каскада)? - PullRequest
0 голосов
/ 27 апреля 2020

Я разрабатываю веб-приложение типа REST с Angular (Typescript) для внешнего интерфейса и Spring (boot, rest, data, hibernate) для внутреннего интерфейса, который подключен к базе данных MySQL. В этом приложении я использую аннотацию JPA.

Все мои отношения между объектами являются двунаправленными:

  • У пользователя есть один адрес, а адрес может соответствовать одному или нескольким Пользователь (и): Пользователь n - 1 Адрес
  • Пользователь предоставляет один или несколько отчетов, а отчет предоставляется только одним пользователем: Пользователь 1 - n Отчет
  • Пользователь n - n Роль (поэтому таблица ассоциации User_Role)
  • Пользователь n - n Группа (поэтому таблица ассоциации User_Group)

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

In User. java

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "userId")
private Long userId;
private String firstName;
private String lastName;
private String email;
...

@JsonSerialize(using = AddressCustomSerializer.class)
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="address_id")
private Address address;

@ManyToMany
@JoinTable( name = "user_role",
    joinColumns = @JoinColumn( name = "role_id" ),
    inverseJoinColumns = @JoinColumn( name = "user_id" ) )
private List<Role> roles = new ArrayList<>();

@OneToMany(mappedBy = "user")
private List<Report> report = new ArrayList<>();

// List of groups the user belongs to.
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
    name = "user_group", 
    joinColumns = { @JoinColumn(name = "user_id") }, 
    inverseJoinColumns = { @JoinColumn(name = "group_id") }
)
private List<Group> userGroups = new ArrayList<>();

In Address. java

@OneToMany(mappedBy = "address")
private List<User> users = new ArrayList<>();

В роли. java

@JsonSerialize(using = UserListForRoleCustomSerializer.class)
@ManyToMany(mappedBy = "roles")
private List<User> users = new ArrayList<>();

В группе. java

// List of users included in the group.
@JsonSerialize(using = UserListForGroupCustomSerializer.class)
@ManyToMany(mappedBy = "userGroups")
private List<User> users = new ArrayList<>();

Когда я нажимаю на пользователя, мой бэкэнд отправляет мне файл json, содержащий все значения для пользовательские атрибуты и все связанные объекты, что в порядке. Но когда я изменяю простой атрибут пользователя, такой как имя или фамилия, я должен отправить в бэкэнд файл json, содержащий все атрибуты и все связанные объекты. Если нет, Hibernate удаляет связанные объекты, подразумеваемые в отношении «многие-к-одному» («Адрес») и «многие-ко-многим» («Роль, группы»), как показано ниже в SQL трассировках:

2020-04-27 12:06:20.786 DEBUG 12032 --- [nio-8080-exec-1] org.hibernate.SQL : update user set address_id=?, charter_acceptance_date=?, creation_date=?....

Столбец "address_id" имеет значение NULL, но соответствующий адрес все еще находится в таблице адресов.

2020-04-27 12:06:20.787 DEBUG 12032 --- [nio-8080-exec-1] org.hibernate.SQL : delete from user_role where role_id=?

В таблице ассоциации "User_Role" строка, содержащая «user_id» и «role_id», удаляется. Но соответствующая роль все еще находится в таблице ролей, а соответствующий пользователь все еще находится в таблице пользователей.

2020-04-27 12:06:20.788 DEBUG 12032 --- [nio-8080-exec-1] org.hibernate.SQL : delete from user_group where user_id=?

Та же проблема в таблице ассоциации "User_Group".

1) Насколько я понимаю, если я не отправляю все связанные сущности, Hibernate "думает", что пользователь на стороне владельца (родительская сущность) больше не связан с сущностями, и hibernate удаляет эти ссылки , Что касается отношения «Пользователь 1 - n Отчет», ссылка между Пользователем и Отчетом не удаляется, так как Отчет является владельцем (родитель). Но когда я захочу изменить простой атрибут отчета, у меня возникнет та же проблема. Я прав?

2) Как избежать этой проблемы, зная, что:

  • Я не хотел бы отправлять файл json, содержащий ВСЕ атрибуты и ВСЕ связанные объекты, если я изменяю только простой атрибут пользователя.
  • Я бы хотел сам управлять тем, какая ссылка или объект удаляется или обновляется, когда я изменяю или удаляю связанный объект (владелец- или нет).
  • В моей базе данных будут тройные и четвертичные отношения. Мне нужно будет настроить каждое обновление и удаление, объект за объектом.

3) Сначала я использовал каскады Hibernate (CascadeType.MERGE и CascadeType.PERSIST) для всех отношений цитируется в моем коде. Но:

  • У меня была такая же проблема;
  • И кто-то сказал мне, что каскады гибернации должны быть зарезервированы для отношения композиции UML. Например: если я удаляю пользователя и хочу, чтобы все его / ее отчеты были удалены. Но это не моя необходимость! Если я удаляю пользователя, я хочу сохранить его / ее отчеты. Что вы думаете о том, что каскады гибернации должны быть зарезервированы для отношения композиции UML?

Заранее большое спасибо за ваши ответы.

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