java - 如何在 Hibernate 中持久化具有两个多对一双向依赖的实体?
问题描述
我在数据库中有以下关系实体:
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
表 B 包含表 A 和 J 的外键。表 C 包含表 B 和 J 的外键。
注意:表 B 和 C 都包含一个外键引用 (TABLE_J_ID),引用表 J。
如您所见,表 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;
}
对象图/树的构建方式:
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);
}
}
}
当我执行代码时,我收到以下错误:
**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**
有人可以告诉我问题是什么吗?
解决方案
问题是:
插入第一个 A。然后将 A_ID 用作 B 中的 FK。插入 B。B 也需要 J_ID FK,但 J 尚未存储 = 瞬态。
JPA 创建插入的顺序应该改变。创建 B、C 需要 J_ID。在将 J 添加到 B、C 之前保持 J。
for (TableB b : bList) {
TableJ j = new TableJ();
em.persist(j)
j.addTableB(b);
tableA.addTableB(b);
}
还有另一个循环
推荐阅读
- hazelcast-jet - 如何对异步接收数据的 hazelcast jet 源进行编程
- ant - 使用 ant 从共享位置获取/下载 jar
- c# - System.IO.FileLoadException:'无法加载文件或程序集'EntityFramework或其依赖项之一。访问被拒绝。
- python - 无法在端口 8000 上的谷歌云访问我的 django 应用程序
- php - 尝试显示 OPCache 的状态时出错。Laravel 和 appstract/laravel-opcache
- python - 查找最大空闲时间块
- javascript - Liferay 7 上的 Portlet 部署问题
- c - Binary Bomb Phase 5 - 寻找两个整数作为输入
- php - 如何使用 api 在 Dynamics crm 中设置leadsource?
- html - 如何将此行与 flexbox 对齐?