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开发

spring data jpa怎么和solr整合

spring data jpa问题

Spring Data 系列 Spring+JPA(spring-data-commons)

spring-data-jpa软删除方案

spring data jpa 详解