在 Hibernate 中,如何自动检索父 id 并在子插入中将其用作外键?
Posted
技术标签:
【中文标题】在 Hibernate 中,如何自动检索父 id 并在子插入中将其用作外键?【英文标题】:In Hibernate, how to automatically retrieve parent id and use it in child insertion as foreign key? 【发布时间】:2014-10-16 08:36:40 【问题描述】:我想要的操作:如果需要,在子表中插入一行会自动在父表中插入一行,否则使用父表中现有行的id作为插入行中的外键子表。
我想知道是否有任何方法可以使用单个 session.save(child)
语句在休眠中执行上述操作。
我正在使用带有 Java 和 SQLite 的 Hibernate。 以下是我对数据库和配置的详细说明:
父表:
id (int): primary key, description (text): unique
表子:
id(int): primary key, address (text), parent_id (integer): foreign key refers Parent(id) [UNIQUE ( address, parent_id )]
POJO 家长:
int id, String description, Set<Child> children, [getters and setters]
POJO 孩子:
int id, String address, Parent parent, [getters and setters]
父.hbm:
...
<id column="id" name="id" type="long">
<generator class="native"/>
</id>
<property column="description" name="description" type="string" unique="true" />
<set fetch="select" inverse="true" lazy="true" name="children" table="Child">
<key>
<column name="parent_id" not-null="true"/>
</key>
<one-to-many class="Child"/>
</set>
...
Child.hbm:
....
<id column="id" name="id" type="long">
<generator class="native"/>
</id>
<property column="address" name="address" type="string"/>
<many-to-one cascade="save-update" class="Parent" fetch="select" name="parent">
<column name="parent_id" not-null="true"/>
</many-to-one>
...
到目前为止,如果父级(具有相同的“描述”)不存在,则父级与子级一起插入。否则,由于唯一的“描述”要求,父级插入失败,因此不会插入子级。
由于插入子对象时我不知道父对象的id(我只知道父对象的描述),因此我无法执行 session.load(Parent.class, parentId) 来检索父对象并使用它插入孩子。我现在正在做的事情如下:
Parent parent = new Parent();
parent.setDescription("D1");
Child child = new Child();
child.setAddress("A1");
parent.getChildren().add(child);
child.setParent(parent);
session.save(child);
我知道我总是可以先通过执行查询select id from Parent where description="D1"
来查找父 ID,然后如果结果集为空,则按照我现在的做法保存子 ID(它也会插入父 ID),如果结果不为空,使用session.load()
加载父对象并使用它插入子对象。但我认为 hibernate 可以在单个 session.save(child)
后面为我处理这个问题。可以吗?
【问题讨论】:
我也有同样的问题。你找到解决办法了吗? 【参考方案1】:试试这个步骤;
1.更改您的 Parent.hbm
...
<id column="id" name="id" type="long">
<generator class="native"/>
</id>
<property column="description" name="description" type="string" unique="true" />
<set fetch="select" inverse="true" lazy="true" name="children" table="Child" cascade="save-update">
<key>
<column name="parent_id" not-null="true"/>
</key>
<one-to-many class="Child"/>
</set>
...
2.改变你的 Child.hbm
....
<id column="id" name="id" type="long">
<generator class="native"/>
</id>
<property column="address" name="address" type="string"/>
<many-to-one class="Parent" fetch="select" name="parent">
<column name="parent_id" not-null="true"/>
</many-to-one>
...
3.并根据需要在父级之前添加子级
Parent parent = new Parent();
parent.setDescription("D1");
Child child = new Child();
child.setAddress("A1");
child.setParent(parent);
session.save(child);
Set<Child> childsSet = new HashSet<Child>();
childsSet.add(child);
parent.setChildren(childsSet);
session.save(parent);
【讨论】:
在 Parent 中没有包含描述的行时有效,但在随后插入与具有相同描述的父关联的子(具有不同地址)时失败(需要唯一的列描述)。后一种情况是我的应用程序中更常见的情况,其中将插入已存在父级的子级,但有时它可能具有数据库中尚不存在的父级,在这种情况下,也需要插入父级。我希望应用程序逻辑通过使用单个session.save(child)
(或 session.save(parent)
)来了解这些情况以上是关于在 Hibernate 中,如何自动检索父 id 并在子插入中将其用作外键?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Hibernate 插入记录正确自动生成主键 ID
如何在JPA / JAVA / Hibernate的两列中插入自动生成的ID