【发布时间】:2015-01-11 08:32:45
【问题描述】:
假设有两个实体:Parent 和 Child,@OneToMany 从 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;
}
如您所见,在我的例子中,Child 表存储了 Parent 主键的外键。但我不希望它作为我的子实体中的双向映射。
现在出现的问题是,我无法在 Child 实例中设置 parent_id。
我创建了这样的实例:
Parent parent = new Parent();
parent.setChildren(Lists.newArrayList(new Child(), new Child()));
parentDomainService.save(parent);
假设在 Parent 端有级联。这种方法首先保存 Parent,然后保存 Child 实例。然后它在子实例上运行更新查询以更新parent_id,正如我从 Hibernate show_sql 日志中看到的那样。但令人惊讶的是,更新查询后,我看到一些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());
除了以下例外,这个反弹了我:
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.somepkg.Child
除了那个例外,我已经看到了很多关于 SO 的问题,而且我知道那里有很多问题,但几乎所有问题都在处理双向映射或使用 JoinTable 的单向映射。它们都不适合我的情况。
这个有灯吗?我别无选择。
P.S.:我正在处理的实际场景需要保存大量数据。例如:50000 条父记录和 250000 条子记录。这就是为什么我不想要双向映射。因为保存 Child 会在后端创建一个带有连接表的查询。
我最感兴趣的是解决方案,其中我不必在Child 表上触发两次查询。正如我当前的应用程序中发生的那样,这会影响性能。
【问题讨论】:
标签: java mysql spring hibernate