Hibernate OneToOne 关系删除子实体导致删除整个父实体行

问题描述

我的应用程序存在以下问题。

定义: 我有3张桌子。用户、密码和确认令牌。用户表是父表。密码表和确认令牌表是与用户表具有一对一关系的子表。用户和确认表 ID 作为外键存储在用户表中。

问题:

用户激活他的帐户时,应从确认令牌表中删除确认令牌行。因此,用户表中的列也应该被删除

我的收获: 使用以下方案,发生的情况是,当我删除确认令牌时,整个用户行数据也会被删除,但密码行数据不会被删除。我想要的是,当删除确认令牌时,只应删除用户表中的相应行和外键列。

public class User {

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private int userId;

 private String username;
 private String email;
 private UserStatus status;
 private LocalDateTime registerDate;
 private LocalDateTime lastLoginDate;

 @OnetoOne(fetch = FetchType.LAZY)
 @JoinColumn(name = "PASSWORD_ID",referencedColumnName = "passwordId")
 private UserPasswords userPassword;

 @OnetoOne(fetch = FetchType.LAZY)
 @JoinColumn(name = "ACCOUNT_CONFIRMATION_TOKEN_ID")
 private ConfirmationToken confirmationToken;}



@Entity
public class ConfirmationToken {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int tokenId;
private String confirmationToken;
private LocalDateTime creationDate;

  @OnetoOne(fetch = FetchType.LAZY,mappedBy = "confirmationToken",cascade=CascadeType.REMOVE,optional=true)
  private User user;

}

 @Entity
 @Table(name = "USER_PASSWORDS")
 public class UserPasswords {

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private int passwordId;

 private String password;
 private String beforePassword;
 private int wrongPasswordTrial;
 private LocalDateTime wrongPasswordDate;
 private LocalDateTime lastPasswordUpdate;

 @OnetoOne(fetch = FetchType.LAZY,mappedBy = "userPassword")
 private User user;

解决方法

发生这种情况是因为设置了 cascade=CascadeType.REMOVE。当相应的 User 行被删除时,这会设置 ConfirmationToken 实体被删除。

使用 DELETE 语句无法仅删除列的值。这只能通过 UPDATE 语句完成。 DELETE 将始终删除整行。

为了实现您想要的效果,您可以将连接列移动到 ConfirmationToken 表,方法是将 @JoinColumn 注释移动到 ConfirmationToken 实体中的映射。这里:

@OneToOne(fetch = FetchType.LAZY,mappedBy = "confirmationToken",optional=true)
@JoinColumn(name = "ACCOUNT_CONFIRMATION_TOKEN_ID")
private User user;

这会将您要删除的列移动到将删除整行的表中。这完全不需要 UPDATE 语句。