我有三个实体:凭证,用户和管理员。 User和Admin实体都具有字段凭据,该字段凭据使用OneToOne注释与Credentials实体相关。
在更新现有的User或Admin条目时,通过entityManager.merge,我在Credentials.login列上获得了重复的密钥,该列具有唯一的约束。
@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,但是我收到错误消息“ keyin_UNIQUE的重复条目'loginname'。对于Admin实体也是如此。”
在此先感谢您的帮助。
答案 0 :(得分:1)
您可能会收到此错误的原因是由于merge
将分离实体的内容复制到托管实体中。因此,如果您将包含分离的merge
或User
实体(从现在起称为Admin
)作为参数传递给PERSON
> Credentials
实体的副本保留在数据库中;那么您肯定会遇到这个问题。原因是:
merge
会将PERSON
实体参数的整个状态复制到相应的上下文托管 PERSON
实体中。Credentials
参数内包含PERSON
实体。Credentials
实体已分离,因此持久性管理器将假定该实体对应于尚未持久的实体。Credentials
(坚持使用新的INSERT
)而不是{{ 1}}。Credentials
将在您获得的UPDATE
字段上触发重复约束约束,因为原始INSERT
记录存在,而login
值在{ {1}}。编辑:(如何合并)
如果您不更新Credentials
中的login
,那么在合并INSERT
时,您可以:
Credentials
(PERSON
)中删除PERSON_DAO
。Credentials
。PERSON
添加回您的新合并的 null
由于我无权访问您的PERSON
代码,因此以下是先前代码的伪代码:
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
希望这会有所帮助。