Java OneToMany双向映射未保存其外键

Java OneToMany双向映射未保存其外键,java,hibernate,Java,Hibernate,我在员工和电话实体之间有一对多关系,如下所示: @Entity public class Employee { @Id @Column(name = "EMP_ID") private long id; private String name; @OneToMany(mappedBy = "owner") private List<Phone> phones = new ArrayList<Phone>(); } @E

我在员工和电话实体之间有一对多关系,如下所示:

@Entity
public class Employee {
    @Id
    @Column(name = "EMP_ID")
    private long id;

    private String name;

    @OneToMany(mappedBy = "owner")
    private List<Phone> phones = new ArrayList<Phone>();
}

@Entity
public class Phone {
    @Id
    private long id;
    private String phoneNumber;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "OWNER_ID")
    private Employee owner;
}
然后我查看并插入查询以保存员工,然后插入查询以保存电话,然后更新查询以更新电话表中的所有者id

因此,为了避免在电话表上插入和更新,我在我的电话实体中添加了以下映射:

@Entity
public class Phone {
    ...
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "OWNER_ID", insertable=false, updatable=false)
    private Employee owner;
}
在本例中,我在Employee上看到insert,然后在Phone上看到insert,但所有者id为null


如何确保在保存实体时所有者id不为空?我想在我的代码中保存Phone然后再保存Employee,而不是相反。

因为Phone是一个子实体,所以需要引用Employee进行保存。 通过使用cascadeType注释电话,您的电话将与您的员工实体一起保存。您修改的实体如下所示:

@Entity
public class Employee {
    @Id
    @Column(name = "EMP_ID")
    private long id;

    private String name;

    @OneToMany(mappedBy = "owner",cascade = CascadeType.ALL)
    private List<Phone> phones = new ArrayList<Phone>();

  /*getters and setters*/
}

@Entity
public class Phone {
    @Id
    private long id;
    private String phoneNumber;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "OWNER_ID", insertable=false, updatable=false,nullable=false)
    private Employee owner;
    /*getters and setters*/

}
@实体
公营雇员{
@身份证
@列(name=“EMP\u ID”)
私人长id;
私有字符串名称;
@OneToMany(mappedBy=“owner”,cascade=CascadeType.ALL)
私有列表电话=新的ArrayList();
/*接球手和接球手*/
}
@实体
公用电话{
@身份证
私人长id;
私有字符串电话号码;
@manytone(fetch=FetchType.LAZY)
@JoinColumn(name=“OWNER\u ID”,insertable=false,updateable=false,nullable=false)
私人雇员业主;
/*接球手和接球手*/
}
并且必须修改您的保存逻辑,如下所示:

Employee emp = new Employee();
private List<Phone> phones = new ArrayList<Phone>();
Phone phone = new Phone();
phone.setOwner(emp);

phones.add(phone);

emp.setPhones(phones);

session.save(emp);
Employee emp=新员工();
私有列表电话=新的ArrayList();
电话=新电话();
设置所有者(emp);
电话。添加(电话);
电磁波固定电话(电话);
会话保存(emp);

根据您的要求,无需使用双向。尝试以下步骤

  • 只需在Phone实体中声明
    @ManyToOne
    。因此,从员工实体中删除
    @OneToMany
    声明
  • Hibernate
    session.save(obj)
    返回对象的id。所以,只需先保存Phone并捕获
    id
    ,然后保存employee即可。参见示例

     session.save(phone);
     long phoneOneId = phone.getId();
     Phone phoneOne = new Phone();
     phoneOne.setId(phoneOneId);
     // You can also add another phone like phoneTwo, phoneThree, ...
     List<Phone> phones = new ArrayList<Phone>();
     phones.add(phoneOne);
     employee.setPhones(phones);
    
    session.save(电话);
    long phoneOneId=phone.getId();
    Phone phoneOne=新手机();
    phoneOne.setId(phoneOneId);
    //您还可以添加另一部手机,如phoneTwo、phoneTwo等。。。
    列表电话=新的ArrayList();
    phones.add(phoneOne);
    员工。设置电话(电话);
    

  • 我不想在这里使用cascade,您正在保存员工,但我想先保存电话,然后再显式保存员工。所以我的方法不可能吗?@user3181365我猜不可能,因为您说过在保存手机时需要
    OWNER\u ID
    作为非空字段。在这种情况下,
    Phone
    将不会首先保存,并将抛出错误,因为
    OWNER\u ID
    为空。因此,必须先保存员工,然后保存电话。
     session.save(phone);
     long phoneOneId = phone.getId();
     Phone phoneOne = new Phone();
     phoneOne.setId(phoneOneId);
     // You can also add another phone like phoneTwo, phoneThree, ...
     List<Phone> phones = new ArrayList<Phone>();
     phones.add(phoneOne);
     employee.setPhones(phones);