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
我有一个双向一对一关系,我希望其中一个实体的 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