简体   繁体   English

如何在 Hibernate 中持久化具有两个多对一双向依赖关系的实体?

[英]How to Persist an Entity with Two Many-to-One Bidirectional Dependencies in Hibernate?

I have the following relational entities in database:我在数据库中有以下关系实体:

Table A <-- (One-to-Many) --> Table B
Table B <-- (One-to-Many) --> Table C
Table B <-- (Many-to-One) --> Table J
Table C <-- (Many-to-One) --> Table J

Table B contains foreign keys to Table A and J. Table C contains foreign keys to Table B and J.表 B 包含表 A 和 J 的外键。表 C 包含表 B 和 J 的外键。

Note: Both Table B and C contain a foreign key reference (TABLE_J_ID), referencing Table J.注意:表 B 和 C 都包含外键引用 (TABLE_J_ID),引用表 J。

As you can see, both Table B and C have Many-to-One relation with Table J. As such, I have created the following bidirectional entities:如您所见,表 B 和 C 都与表 J 具有多对一关系。因此,我创建了以下双向实体:

@Entity
@Table(name="TableA")
public class TableA {
  @Id
  // Generates via a sequence object
  private Integer id;

  @OneToMany(mapped="tableATableB", cascade=CascadeType.All, orphanRemoval=true)
  private Set<TableB> tableBs = new LinkedHashSet<TableB>();

  public void addTableB(TableB b) {
    this.tableBs.add(b);
    b.setTableATableB(this);
  }
}

@Entity
@Table(name="TableB")
public class TableB {
  @Id
  // Generates via a sequence object
  private Integer id;

  @ManyToOne
  @JoinColumn(name="TABLE_J_ID")
  private TableJ tableJTableB;

  @ManyToOne
  @JoinColumn(name="TABLE_A_ID")
  private TableA tableATableB;

  @OneToMany(mapped="tableBTableC", cascade=CascadeType.All, orphanRemoval=true)
  private Set<TableC> tableCs = new LinkedHashSet<TableC>();

  public void addTableC(TableC c) {
    this.tableCs.add(c);
    b.setTableBTableC(this);
  }
}

@Entity
@Table(name="TableJ")
public class TableJ {
  @Id
  // Generates via a sequence object
  private Integer id;

  @OneToMany(mapped="tableJTableB", cascade=CascadeType.All)
  private Set<TableB> tableBs = new LinkedHashSet<TableB>();

  @OneToMany(mapped="tableJTableC", cascade=CascadeType.All)
  private Set<TableC> tableCs = new LinkedHashSet<TableC>();

  public void addTableB(TableB b) {
    this.tableBs.add(b);
    b.setTableJTableB(this);
  }

  public void addTableC(TableC c) {
    this.tableCs.add(c);
    b.setTableJTableC(this);
  }

}

@Entity
@Table(name="TableC")
public class TableC {
  @Id
  // Generates via a sequence object
  private Integer id;

  @ManyToOne
  @JoinColumn(name="TABLE_J_ID")
  private TableJ tableJTableC;

  @ManyToOne
  @JoinColumn(name="TABLE_B_ID")
  private TableB tableBTableC;

}    

The way the object graph/tree is built:对象图/树的构建方式:

TableA tableA = new TableA();

// Get a list of TableB's (bList) from an external call
// THIS BASICALLY ADDS TABLE B's to TABLE A and TABLE J
for (TableB b : bList) {
  TableJ j = new TableJ();
  j.addTableB(b);

  tableA.addTableB(b);

}

// Get a list of TableC's (cList) from an external call
// THIS BASICALLY ADDS TABLE C's to TABLE B and TABLE J
for (TableC c : cList) {

  for (TableB b : tableA.getTableBs()) {
    // Iterate through bList and find a match per some logic
    if (/* some logic to find a corresponding TableB */) {
      TableJ j = new TableJ();
      j.addTableC(c);

      b.addTableC(c);
    }

  }
}

When I execute the code, I get the following error:当我执行代码时,出现以下错误:

**Unexpected error occurred in scheduled task.: org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: object TableB.tableJTableB -> class TableJ; nested exception in java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing: TableB.tableJTableB -> class TableJ

Caused by: java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing: TableB.tableJTableB -> class TableJ**

Can someone tell me what the issue is?有人可以告诉我这是什么问题吗?

The issue is:问题是:

First A is inserted.首先插入A。 Then A_ID is used as FK in B. B is inserted.然后 A_ID 用作 B 中的 FK。插入 B。 B also needs J_ID FK, but J was not stored yet = transient. B 还需要 J_ID FK,但 J 尚未存储 = 瞬态。

The order how JPA is creating inserts should be changed. JPA 创建插入的顺序应该改变。 J_ID is needed to create B,C.创建 B、C 需要 J_ID。 Persist J before adding it to B,C.在将 J 添加到 B、C 之前坚持 J。

for (TableB b : bList) {
  TableJ j = new TableJ();
  em.persist(j)
  j.addTableB(b);
  tableA.addTableB(b);
}

also the other loop还有另一个循环

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM