假设有两个实体:父和 Child ,{em}从 Parent 到 Child { EM>
@OneToMany
正如您所看到的,在我的例子中, Child 表将一个外键存储到 Parent 的主键中。但我不希望在我的Child实体中将其作为双向映射。
现在出现的问题是,我无法在class Parent {
@Column(name="id")
private Long id;
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id", referencedColumnName = "id")
private List<Child> children;
}
class Child {
@Column(name="id")
private Long id;
@Column(name="parent_id")
private Long parentId;
}
个实例中设置parent_id
。
我创建了这样的实例:
Child
假设父端有级联。此方法首先保存Parent,然后保存Child实例。然后它在子实例上运行更新查询以更新Parent parent = new Parent();
parent.setChildren(Lists.newArrayList(new Child(), new Child()));
parentDomainService.save(parent);
,正如我从Hibernate show_sql日志中看到的那样。但令人惊讶的是,在更新查询后,我看到一些parent_id
,child
是parent_id
。这让我很惊讶。
所以,我去手动处理那件事,并删除了级联。然后我保存了这样的实体:
null
这一个反弹在我身上,但有以下例外:
Parent parent = new Parent();
parent.setChildren(Lists.newArrayList(new Child(), new Child()));
parent = parentDomainService.save(parent);
for (Child child: parent.getChildren()) {
child.setParentId(parent.getId());
}
childDomainService.save(parent.getChildren());
我在SO上看到了很多关于异常的问题,而且我知道有很多问题,但是几乎所有问题都在处理双向映射,或者使用JoinTable进行单向映射。它们都不适合我的情况。
这有什么灯吗?我没有选择。
P.S。:我正在处理的实际场景需要节省大量数据。例如:50000个父记录和250000个子记录。这就是为什么我不想要双向映射。因为保存Child会在后端创建一个带有连接表的查询。
我最感兴趣的是解决方案,其中我不必在org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.somepkg.Child
表上触发两次查询。正如我当前的应用程序中发生的那样,这妨碍了性能。
答案 0 :(得分:4)
删除级联时,父级不会保留引用的子元素,而是
parent = parentDomainService.save(parent);
父引用“未保存的瞬态”子实例,因此抛出异常。如果您先保存父项,然后添加子项:
Parent parent = new Parent();
parent = parentDomainService.save(parent);
parent.setChildren(Lists.newArrayList(new Child(), new Child()));
for (Child child: parent.getChildren()) {
child.setParentId(parent.getId());
}
childDomainService.save(parent.getChildren());
然后不会抛出异常。