Hibernate 一对多关系不为外键提供值
Hibernate one to many relationship does not provide value for foreign key
我已经有一段时间没有使用 Hibernate 了,前几天我想做一些简单的例子,但是当我需要做一个一对多的关系时,多边没有被插入到数据库中。这是数据库的样子。
这是我给这个人的映射:
Java
public class ORMPerson implements Serializable {
private Long uniqueId;
private String firstName;
private String secondName;
private Long fkAddress;
hbm
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="orm">
<class name="orm.ORMPerson" table="PERSON">
<id name="uniqueId" column="UNIQUE_ID">
<generator class="increment"/>
</id>
<property name="firstName" column="FIRST_NAME"/>
<property name="secondName" column="SECOND_NAME"/>
<many-to-one name="fkAddress" class="orm.ORMPerson" column="FK_ADDRESS" cascade="all" not-null="false" />
</class>
</hibernate-mapping>
这是地址的映射:
Java
public class ORMAddress implements Serializable {
private Long uniqueId;
private String firstLine;
private String secondLine;
private String postcode;
private Set<ORMPerson> ormPersons;
hbm
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="orm">
<class name="orm.ORMAddress" table="ADDRESS">
<id name="uniqueId" column="UNIQUE_ID">
<generator class="increment"/>
</id>
<property name="firstLine" column="FIRST_LINE"/>
<property name="secondLine" column="SECOND_LINE"/>
<property name="postcode" column="POSTCODE"/>
<set name="ormPersons" table="ADDRESS" inverse="true" fetch="select" cascade="save-update">
<key>
<column name="UNIQUE_ID" not-null="true" />
</key>
<one-to-many class="ORMPerson"/>
</set>
</class>
</hibernate-mapping>
这是我用来插入多人地址的客户端代码:
ORMAddress ormAddress = new ORMAddress();
ormAddress.setFirstLine(address.getFirstLine());
ormAddress.setSecondLine(address.getSecondLine());
ormAddress.setPostcode(address.getPostcode());
ormAddress.setOrmPersons(ormPersons);
session.save(ormAddress);
session.getTransaction().commit();
如果我尝试用 ormPersons 调用 session.save() 方法,我会看到数据被添加到数据库中,但外来 kew 将没有任何价值。我认为这是因为我在 Person 中只有一个 not-null="false" 但这不是解决方案,我认为只需调用一次保存方法就可以自动插入所有内容。
原因隐藏在inverse="true"
映射中。这是对 Hibernate 说:
when you persist collection - let that job on its items. These items must be aware of their parent.
但是正如我们在上面看到的,ormPersons
没有提供对 ormAddress 的反向引用。
...
// after that line we have to do more
ormAddress.setOrmPersons(ormPersons);
// we have to assign back reference
for(ORMPerson ormPerson: ormPersons) {
ormPerson.setOrmAddress(ormAddress);
}
而且我们还需要 ORMPerson 内部的 ORMAddress 引用 - 而不是 LONG
public class ORMPerson implements Serializable {
...
private ORMAddress ormAddress;
hbm
<class name="orm.ORMPerson" table="PERSON">
....
<many-to-one name="ormAddress" class="orm.ORMPerson"
column="FK_ADDRESS" cascade="all" not-null="false" />
</class>
最后,多对一和一对多必须使用相同的列
hbm 地址 (FK_ADDRESS):
<class name="orm.ORMAddress" table="ADDRESS">
...
<set name="ormPersons" table="ADDRESS" inverse="true"
fetch="select" cascade="save-update">
<key>
//<column name="UNIQUE_ID" not-null="true" />
<column name="FK_ADDRESS" not-null="true" /> // the parent id
</key>
<one-to-many class="ORMPerson"/>
</set>
查看文档以获取示例:
我已经有一段时间没有使用 Hibernate 了,前几天我想做一些简单的例子,但是当我需要做一个一对多的关系时,多边没有被插入到数据库中。这是数据库的样子。
这是我给这个人的映射:
Java
public class ORMPerson implements Serializable {
private Long uniqueId;
private String firstName;
private String secondName;
private Long fkAddress;
hbm
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="orm">
<class name="orm.ORMPerson" table="PERSON">
<id name="uniqueId" column="UNIQUE_ID">
<generator class="increment"/>
</id>
<property name="firstName" column="FIRST_NAME"/>
<property name="secondName" column="SECOND_NAME"/>
<many-to-one name="fkAddress" class="orm.ORMPerson" column="FK_ADDRESS" cascade="all" not-null="false" />
</class>
</hibernate-mapping>
这是地址的映射:
Java
public class ORMAddress implements Serializable {
private Long uniqueId;
private String firstLine;
private String secondLine;
private String postcode;
private Set<ORMPerson> ormPersons;
hbm
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="orm">
<class name="orm.ORMAddress" table="ADDRESS">
<id name="uniqueId" column="UNIQUE_ID">
<generator class="increment"/>
</id>
<property name="firstLine" column="FIRST_LINE"/>
<property name="secondLine" column="SECOND_LINE"/>
<property name="postcode" column="POSTCODE"/>
<set name="ormPersons" table="ADDRESS" inverse="true" fetch="select" cascade="save-update">
<key>
<column name="UNIQUE_ID" not-null="true" />
</key>
<one-to-many class="ORMPerson"/>
</set>
</class>
</hibernate-mapping>
这是我用来插入多人地址的客户端代码:
ORMAddress ormAddress = new ORMAddress();
ormAddress.setFirstLine(address.getFirstLine());
ormAddress.setSecondLine(address.getSecondLine());
ormAddress.setPostcode(address.getPostcode());
ormAddress.setOrmPersons(ormPersons);
session.save(ormAddress);
session.getTransaction().commit();
如果我尝试用 ormPersons 调用 session.save() 方法,我会看到数据被添加到数据库中,但外来 kew 将没有任何价值。我认为这是因为我在 Person 中只有一个 not-null="false" 但这不是解决方案,我认为只需调用一次保存方法就可以自动插入所有内容。
原因隐藏在inverse="true"
映射中。这是对 Hibernate 说:
when you persist collection - let that job on its items. These items must be aware of their parent.
但是正如我们在上面看到的,ormPersons
没有提供对 ormAddress 的反向引用。
...
// after that line we have to do more
ormAddress.setOrmPersons(ormPersons);
// we have to assign back reference
for(ORMPerson ormPerson: ormPersons) {
ormPerson.setOrmAddress(ormAddress);
}
而且我们还需要 ORMPerson 内部的 ORMAddress 引用 - 而不是 LONG
public class ORMPerson implements Serializable {
...
private ORMAddress ormAddress;
hbm
<class name="orm.ORMPerson" table="PERSON">
....
<many-to-one name="ormAddress" class="orm.ORMPerson"
column="FK_ADDRESS" cascade="all" not-null="false" />
</class>
最后,多对一和一对多必须使用相同的列
hbm 地址 (FK_ADDRESS):
<class name="orm.ORMAddress" table="ADDRESS">
...
<set name="ormPersons" table="ADDRESS" inverse="true"
fetch="select" cascade="save-update">
<key>
//<column name="UNIQUE_ID" not-null="true" />
<column name="FK_ADDRESS" not-null="true" /> // the parent id
</key>
<one-to-many class="ORMPerson"/>
</set>
查看文档以获取示例: