【问题标题】:Spring Data JPA + Postgres - Unable to insert data with One to One mappingSpring Data JPA + Postgres - 无法使用一对一映射插入数据
【发布时间】: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 映射时出现上述错误。好像我的主键有问题。我看到类似的问题,但我找不到这里发生了什么。非常感谢您的帮助。

【问题讨论】:

    标签: spring postgresql spring-boot spring-data-jpa


    【解决方案1】:

    想到两个解决方案:

    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;
         $$; 
    
    1. 处理两个表的插入的单个语句:
         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 中的列。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2021-09-15
    • 2020-11-30
    • 2020-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多