Я разрабатываю веб-приложение типа REST с Angular (Typescript) для внешнего интерфейса и Spring (boot, rest, data, hibernate) для внутреннего интерфейса, который подключен к базе данных MySQL. В этом приложении пользовательский java-объект имеет атрибуты и связан с несколькими списками объектов (публикации, предполагаемое использование, роли, группы пользователей и управляемые группы) с использованием аннотации JPA, как показано ниже.
В файле User.java
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name = "userId")
private Long userId;
private String firstName;
private String lastName;
private String email;
private String photo;
private String instantMessaging;
@Column(length = 50)
private String phoneNumber;
private String personnalURL;
private Timestamp charterAcceptanceDate;
@Column(unique=true)
private String username;
private Timestamp expirationDate;
private String password;
private Timestamp creationDate;
private Timestamp approvedDate;
private boolean isActive;
private boolean isAdmin;
// Relations
@OneToMany(mappedBy = "user", cascade = CascadeType.MERGE, orphanRemoval = true)
private List<Publication> publications = new ArrayList<>();
@OneToMany(mappedBy = "user", cascade = CascadeType.MERGE, orphanRemoval = true)
private List<IntendedUsage> intendedUsages = new ArrayList<>();
@ManyToMany(cascade = CascadeType.MERGE, fetch=FetchType.EAGER)
private List<Role> roles = new ArrayList<>();
// List of groups the user belongs to.
@ManyToMany(cascade = {CascadeType.MERGE}, fetch = FetchType.LAZY)
@JoinTable(
name = "user_group",
joinColumns = { @JoinColumn(name = "user_id") },
inverseJoinColumns = { @JoinColumn(name = "group_id") }
)
private List<Group> userGroups = new ArrayList<>();
// List of groups managed by the user.
@ManyToMany(cascade = {CascadeType.MERGE}, fetch = FetchType.LAZY)
@JoinTable(
name = "managed_group",
joinColumns = { @JoinColumn(name = "user_id") },
inverseJoinColumns = { @JoinColumn(name = "group_id") }
)
private List<Group> managedGroups = new ArrayList<>();
In Role.java
@JsonSerialize(using = UserListCustomSerializer.class)
@ManyToMany(mappedBy = "roles")
private List<User> users = new ArrayList<>();
In Group.java
// List of users included in the group.
@JsonSerialize(using = UserListForGroupCustomSerializer.class)
@ManyToMany(mappedBy = "userGroups")
private List<User> users = new ArrayList<>();
// List of users who are managing the group.
@JsonSerialize(using = ManagerListForGroupCustomSerializer.class)
@ManyToMany(mappedBy = "managedGroups")
private List<User> managerUsers = new ArrayList<>();
В веб-интерфейсе у меня есть форма для изменения характеристик пользователя. Когда я отправляю изменения, веб-интерфейс отправляет бэкэнду файл JSON, подобный следующему:
{
"active":true,
"admin":false,
"approvedDate":"1970-01-01T23:47:13.000+0000",
"charterAcceptanceDate":"1970-01-09T18:44:13.000+0000",
"creationDate":"1970-01-02T10:49:26.000+0000",
"email":"jack.bauer@gmake.com",
"expirationDate":"1970-01-02T10:49:26.000+0000",
"firstName":"Jack",
"instantMessaging":"skype.com",
"lastName":"Bauer",
"login":"","password":"",
"personnalURL":"http://www.jack.com",
"phoneNumber":"0686596352",
"photo":"/home/jjj/",
"userId":1,
"username":"jbauerooooo"
}
Нет информации о публикациях пользователя, предполагаемом использовании, ролях, пользовательских группах и управляемых группах, что является нормой. Здесь я просто хочу изменить общие характеристики пользователя, а не его списки.
Я думал, что с CascadeType.MERGE, если нет информации о списках, связанных с пользователем, существующие списки (записанные в базе данных)останется в базе данных.
Это верно для отношений OneToMany, но НЕ для отношений ManyToMany. Текущая запись данных в базе данных для ролей, пользовательских групп, управляемых групп удаляется, когда веб-интерфейс отправляет файл JSON выше.
Почему? Как избежать этого?
Я пытался использовать CascadeType.ALL, и в этом случае все данные, касающиеся списков, удаляются. Я перепробовал все значения CascadeType для отношений ManyToMany. Это та же проблема.
Заранее спасибо за ответ ...