gpt4 book ai didi

java - 如何在 Hibernate 中级联更新子实体

转载 作者:行者123 更新时间:2023-12-02 08:55:03 25 4
gpt4 key购买 nike

我有三个实体:凭据、用户和管理员。 User 和 Admin 实体都有一个字段凭据,该字段与使用 OneToOne 注释的 Credentials 实体相关。

当通过entityManager.merge更新现有的用户或管理员条目时,我在Credentials.login列上获得了重复的 key ,该列具有唯一的约束。

@Entity
@Table
public class Credentials {
@Id
@Column(name="id", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(unique=true, nullable=false, length=50)
private String login;

@Column(nullable=false, length=50)
private String password;

/*********************************************
* getters and setters here
**********************************************/
}

@Entity
@Table
public class User{
@Id
@Column(name="id", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

/*********************************************
* Specific user columns here
**********************************************/

@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(nullable=false, name = "idCredentials")
private Credentials credentials;

/*********************************************
* getters and setters here
**********************************************/
}

@Entity
@Table
public class Admin{
@Id
@Column(name="id", unique=true, nullable=false)
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

/*********************************************
* Specific admin columns here
**********************************************/

@OneToOne(cascade = {CascadeType.ALL})
@JoinColumn(nullable=false, name = "idCredentials")
private Credentials credentials;

/*********************************************
* getters and setters here
**********************************************/
}

我希望在调用entityManager.merge(user)后在各自的数据库表中更新user和user.credentials,但我收到错误“重复条目'loginname'键'login_UNIQUE”。管理实体也会发生同样的情况。

预先感谢您的帮助。

最佳答案

您可能收到此错误的原因是merge 将分离实体的内容复制到托管实体中。因此,如果您将 merge 作为参数传递给 UserAdmin 实体(从现在起称为 PERSON) >) 包含持久存在数据库中的Credentials实体的分离副本;那么你肯定会遇到这个问题。原因是:

  1. merge 会将 PERSON 实体参数的整个状态复制到相应的上下文管理 PERSON 实体中。
  2. 此副本将在 PERSON 参数内包含 Credentials 实体。
  3. 由于 Credentials 实体已分离,持久性管理器将假定该实体对应于尚未持久化的实体。
  4. 持久化上下文在刷新 session 时,将使用 INSERT 保存合并Credentials(保留新的Credentials)而不是更新
  5. INSERT 将触发您获取的 login 字段上的重复约束违规,因为原始 Credentials 记录与 一起存在INSERT 中使用的 >login 值。

编辑:(如何合并)

如果您没有更新 PERSON 中的 Credentials,那么在合并 PERSON_DAO 时,您可以:

  1. 在合并之前暂时删除 PERSON 中的 Credentials (null)。
  2. 合并PERSON
  3. 将原始Credentials添加回您的新合并的 PERSON

由于我无法访问您的 DAO 代码,这里是前面的伪代码:

    public PERSON mergeSafely(PERSON person) {
Credentials originalCredentials = person.getCredentials();
person.setCredentials(null);
person = em.merge(person);
person.setCredentials(originalCredentials);
return person;
}

如果您还想合并Credentials,那么您应该(为了简洁起见)使用dao层之上的service层。在该层中完成此操作的实用方法的伪代码如下所示:

    public PERSON mergeCompletely(PERSON person) {
Credentials mergedCredentials = credentialsDAO.merge(person.getCredentials());
person.setCredentials(mergedCredentials);
person = personDAO.merge(person);
return person;
}

希望这有帮助。

关于java - 如何在 Hibernate 中级联更新子实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56175515/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com