【问题标题】:Hibernate OneToOne Relationship remove child entity causes to remove whole parent entity rowHibernate OneToOne 关系删除子实体导致删除整个父实体行
【发布时间】:2021-04-06 22:56:01
【问题描述】:

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

定义: 我有 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;

【问题讨论】:

    标签: hibernate one-to-one hibernate-cascade


    【解决方案1】:

    这是因为设置了cascade=CascadeType.REMOVE。当相应的ConfirmationToken 行被删除时,这将设置User 实体被删除。

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

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

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

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

    【讨论】:

    • 您好,感谢您的快速评论。这是否意味着我应该获取用户实例并将 Confirmation_token_id 外键设置为 null,然后使用 crud 接口提供的确认令牌存储库接口删除确认令牌实例
    • 如果您仍然想采用这种方法,可以。然后你最终会执行 2 个 SQL 语句,我不确定,但我认为你需要为用户调用 save() 作为额外的代码行。
    • 您对更好的方法还有其他建议吗?关于管理这种关系。 ?因此,每个用户在注册到该站点时都会有一个确认令牌。一旦通过邮件激活它们,则应删除此令牌。所以我所做的就是将外键放入用户表中,然后执行我上面写的操作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-09
    • 2018-12-04
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    相关资源
    最近更新 更多