使用多级后向引用保存实体

时间:2018-07-23 09:00:55

标签: hibernate jpa

我有这样定义的实体链:

@Entity @Table("A")
class A {
  @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
  Integer id;

  @OneToOne(mappedBy = "a", cascade = [CascadeType.ALL], orphanRemoval = true)
  B b;
}

@Repository
interface RepositoryOfA implements JpaRepository<A, Integer> {}

@Entity @Table("B")
class B {
  @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
  Integer id;

  @OneToOne @JoinColumn(name = "a_id")
  A a;

  @OneToOne(mappedBy = "b", cascade = [CascadeType.ALL], orphanRemoval = true)
  C c;
}

@Embeddable
class CPK implements Serializable {
    @Column(name = "b_id")
    val bId: Long
}

@Entity @Table("C")
class C implements Serializable {

    @EmbeddedId
    CPK id;

    @Column(name = "data")
    String data;

    @OneToOne
    @MapsId("b_id")
    B b;

}

然后我尝试将B类型的实体添加到B类型的现有实体(已定义子项):

A a = repositoryOfA.findById(some_id).orElseThrow(...);
a.b = new B();
b.id = 0;
b.a = a;
b.c = new C();
c.id = new CPK();
c.id.b_id = 0; // ?????
c.b = b;
c.data = "hello";

repositoryOfA.save(a);

然后我得到java.sql.SQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails ('C', CONSTRAINT 'c_id_fk' FOREIGN KEY ('b_id') REFERENCES 'B' ('id') ON DELETE CASCADE ON UPDATE CASCADE)

我了解为什么会发生这种情况,因此我尝试使用无效的b_id保留实体,该实体等于零。但是直觉告诉我,Hibernate应该有一些注释,以便绕过它,因为我不想手动进行两步保存: 1)用B保存一个A,其中B.c = null 2)用C保存A和B

有没有办法在一次通话中执行此操作?

1 个答案:

答案 0 :(得分:0)

问题是@MapsId的使用不正确。根据文档value的{​​{1}}参数应对应于现有实体属性,而不是该列。

@MapsId一样,Hibernate不会抱怨@MapsId指向一个不存在的实体的奇怪事物