Spring Data JPA + Postgres - 无法使用一对一映射插入数据
Posted
技术标签:
【中文标题】Spring Data JPA + Postgres - 无法使用一对一映射插入数据【英文标题】:Spring Data JPA + Postgres - Unable to insert data with One to One mapping 【发布时间】:2021-10-25 23:51:38 【问题描述】:我有一个 UserInfo 和 AddressInfo 实体类,它们有一对一的关联。 UserInfo 使用序列添加主键,但出现以下错误;
org.hibernate.id.IdentifierGenerationException: 试图从空的一对一属性分配 id
用户信息实体
@Entity
@Table(name = "userinfo")
public class UserInfo
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "userid_seq")
@SequenceGenerator(name="userid_seq", allocationSize=1)
private Long userId;
private String firstName;
private String lastName;
private String email;
private String username;
private String password;
@OneToOne(mappedBy = "userInfo", cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private AddressInfo addressInfo;
//Getters - Setters
地址信息实体
@Entity
@Table(name = "addressinfo")
public class AddressInfo
@Id
private Long addressId;
private String homeAddress;
private String homeCity;
private String homeState;
private String homeZip;
@OneToOne
@MapsId
@JoinColumn(name = "address_id")
private UserInfo userInfo;
//Getters - Setters
用户信息表
CREATE TABLE userinfo (
user_id INTEGER NOT NULL DEFAULT nextval('userid_seq') PRIMARY KEY ,
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
username VARCHAR(20) NOT NULL,
password VARCHAR(20) NOT NULL
);
地址信息表
CREATE TABLE addressinfo (
address_id INTEGER NOT NULL PRIMARY KEY,
home_address VARCHAR(100) NULL,
home_city VARCHAR(100) NULL,
home_state VARCHAR(100) NULL,
home_zip VARCHAR(100) NULL,
CONSTRAINT fk_addinfo
FOREIGN KEY(address_id)
REFERENCES userinfo(user_id)
);
我认为我的序列有一些问题,但我可以看到,如果我删除子实体,那么它会成功插入到 UserInfo 表中,但是当我添加 OneToOne 映射时出现上述错误。好像我的主键有问题。我看到类似的问题,但我找不到这里发生了什么。非常感谢您的帮助。
【问题讨论】:
【参考方案1】:想到两个解决方案:
-
插入用户信息和地址信息的单个事务。第二次插入使用序列 currval 来定义 id。
create table addressinfo (
address_id integer default currval('userid_seq') primary key,
home_address varchar(100) null,
home_city varchar(100) null,
home_state varchar(100) null,
home_zip varchar(100) null,
constraint fk_addinfo
foreign key(address_id)
references userinfo(user_id)
);
do $$
begin
insert into userinfo (first_name, last_name, email, username, password)
values ('Jane','Smith','j.smith@thisplace.org','js','psojHvIEJNB');
insert into addressinfo( home_address, home_city, home_state,home_zip)
values ('1 Joe''s Lane','Smithtown', 'NV', '0123456789asdfgh');
end;
$$;
-
处理两个表的插入的单个语句:
with newuser (user_id) as
(insert into userinfo (first_name, last_name, email, username, password)
values ('Joe','Smith','j.s.smith@thisplace.org','js2','+949+fsrgwDGKJS58')
returning user_id
) --select id from newuser;
insert into addressinfo(address_id, home_address, home_city, home_state,home_zip)
select user_id,'1 Joe''s Lane','Smithtown', 'NV', '0123456789asdfgh'
from newuser;
然而,这两者都不是一个好的计划。一对一的关系总是值得怀疑的。在这种情况下,它们不是。当用户 Jane Smith 存储她的地址,然后坚持她的丈夫 Joe 有相同的地址时会发生什么。你最终得到了重复的地址。见example here。您最好给addressinfo
提供自己的PK 序列并将address_id
作为一列并将FK 放入userinfo
【讨论】:
其实你是完全正确的,我看不到这一点。我同意你的建议。将 address_id 添加为 Userinfo 中的列。非常感谢!以上是关于Spring Data JPA + Postgres - 无法使用一对一映射插入数据的主要内容,如果未能解决你的问题,请参考以下文章
spring-data详解之spring-data-jpa:简单三步快速上手spring-data-jpa开发