JPA - 级联坚持一对一的关系

JPA - Cascade persist on one to one relationship

我有一个双向一对一关系,我希望其中一个实体的 ID 也是另一个实体的 ID。

我的代码是这样的:

@Entity
public class UserProfile extends AbstractEntity{
     @OneToOne(mappedBy="user",cascade = CascadeType.ALL)
     private UserPreferences preferences;

     //...
}

另一个实体:

@Entity
public class UserPreferences implements Serializable{
  @Id
  @Column(name="USER_ID")
  private String userId;  // I want USER_ID act as both primary key and foreign key

  @OneToOne
  @PrimaryKeyJoinColumn(name="USER_ID")
  UserProfile user;

  // ...
}

但是当我坚持这样的 UserProfile 时:

UserPreferences pref = new UserPereferences();
pref.setUser(user);
user.setPreferences(pref);
em.persist(user);

它给我一个错误,提示 UserPreferences 的 ID 不能为空 jpa 似乎不明白它应该使用 UserProfile Id 作为 UserPreferences Id。

错误:

Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'USER_ID' cannot be null
Error Code: 1048
Call: INSERT INTO USERPREFERENCES (USER_ID) VALUES (?)

我的代码有问题吗? jpa 可以解决这个问题吗?或者我应该分开保存它们?

提前致谢

使用@MapsId代替@PrimaryKeyJoinColumn

@Entity
public class UserPreferences implements Serializable{
  @Id
  @Column(name="USER_ID")
  private String userId;  // I want USER_ID act as both primary key and foreign key

  @MapsId
  @OneToOne
  //@PrimaryKeyJoinColumn(name="USER_ID")
  UserProfile user;

  // ...
}

这将在 DDL 生成期间创建外键定义。

CREATE TABLE USERPREFERENCE (USER_ID VARCHAR(255) NOT NULL, PRIMARY KEY (USER_ID))
CREATE TABLE USERPROFILE (ID VARCHAR(255) NOT NULL, PRIMARY KEY (ID))
ALTER TABLE SESSION ADD CONSTRAINT FK_SESSION_USER_ID FOREIGN KEY (USER_ID) REFERENCES USER (ID)
ALTER TABLE USERPREFERENCE ADD CONSTRAINT FK_USERPREFERENCE_USER_ID FOREIGN KEY (USER_ID) REFERENCES USERPROFILE (ID)

你不要这样做

@Id
@Column(name="USER_ID")
private String userId;  // I want USER_ID act as both primary key and foreign key

@OneToOne
@PrimaryKeyJoinColumn(name="USER_ID")
UserProfile user;

因为你使用了两次引用,所以只需要使用一次

@OneToOne
@Id
@Column(name="USER_ID")
UserProfile user;

例如这样

注释本身不足以对相关表进行实际级联操作。您还应该在 FK UserPreferences -> UserProfile 上找到 "ON XXX CASCADE"。

如果您使用 JPA 创建 DDL,您应该在 UserPreferences Table 上阅读它。如果已经创建了 DB,则应该删除约束,然后手动添加 CASCADE,如下所示:

 alter table UserPreferences  drop constraint OldConstraintName;
 alter table UserPreferences  add constraint FK_ABABA foreign key (USERID) references UserProfile(USERID) on delete/update/etc.. cascade