java - 为什么CascadeType.MERGE删除数据库中的记录

标签 java angular spring typescript hibernate

我正在开发一个 REST 类型的 Web 应用程序,前端使用 Angular(Typescript),后端使用 Spring(启动、休息、数据、 hibernate ),连接到 MySQL 数据库。 在此应用程序中,用户 java 对象具有属性,并使用 JPA 注释链接到多个对象列表(出版物、预期用途、 Angular 色、用户组和托管组),如下所示。

在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"
}

没有有关用户发布、预期用途、 Angular 色、用户组和托管组的信息,这是正常的。 这里我只想修改用户的一般特征,而不是他的列表。

我认为使用 CascadeType.MERGE,如果没有有关与用户链接的列表的信息,现有列表(记录在数据库中)将保留在数据库中。

这对于 OneToMany 关系是正确的,但对于 ManyToMany 关系则不然。当前端发送上述 JSON 文件时,数据库中当前 Angular 色、用户组、托管组的数据记录将被删除。

为什么? 如何避免这种情况?

我尝试使用 CascadeType.ALL,在这种情况下,所有与列表相关的数据都会被删除。 我尝试了 ManyToMany 关系的 CascadeType 的所有值。这是同样的问题。

预先感谢您的回答...

最佳答案

合并不会做你想象的那样。它相当复杂,我无法解释它的优点,但您可以查找它并应该找到一些不错的文章。当您发送 json 数据时,它会被序列化,即使您没有将其包含在 json 文件中,java 也会将未包含的字段设置为 null。当你保存实体时,hibernate将删除子实体或将字段设置为空(因为在java中它们是空的)。为了实现您的目标,我将在您的实体上使用 @DynamicUpdate 注释。然后您可以创建一个代表部分 json 数据的 DTO。然后在您的服务中通过 id 获取实体并从 DTO 设置其相关字段。延迟加载将确保不会从数据库中提取子级,并且 @DynamicUpdate 将确保只有更新的字段包含在来自 hibernate 的更新 SQL 语句中。这应该是相当有效的。我还建议将属性中的 hibernate.show_sql 标志设置为 true,以便您可以看到 hibernate 在幕后正在做什么。 Hibernate 可以做一些奇怪的事情,有时甚至忽略您的注释。

关于java - 为什么CascadeType.MERGE删除数据库中的记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58271680/

相关文章:

javascript - Angular 4.我无法使用自动完成 - primeNG

java - 属性 'profile' 不允许出现在元素 'beans:bean' 中

Spring boot 1.5.9,访问 Docker 容器中的资源镜像时出现 404 错误

java - 如何使用Mockito进行系统测试?我们应该吗?

javascript - 如何将数据从组件传递到包含数组的 .ts 文件?

angular - Angular 2中输入为空时禁用按钮

java - 在 Spring 中使用 CompletableFuture.exceptionally() 时如何更改响应状态代码?

java - DAO和Service层设计

java - 无法实例化 bean 类 : BeanInstantiationException

Java NIO 非阻塞读取返回超时(linux 内核问题?)