无法在Hibernate中保存具有一对一关系的两个实体?

时间:2016-12-01 10:36:36

标签: java hibernate hibernate-mapping one-to-one

我正在尝试使用Hibernate中的一对一映射,我感到很困惑。我通过一对一关系有两个表Student和Address映射,并为Address表设置外键。我创建了一个将数据保存到数据库的函数,如下所示:

public static void oneToOneMappingWithXML(Session session) throws Exception {
    StudentEntity tom = new StudentEntity();
    tom.setName("Tom");
    tom.setAge(10);
    tom.setClazz("5B");
    tom.setStudentId(1);

    AddressEntity tom_address = new AddressEntity();
    tom_address.setCity("New York");
    tom_address.setAddressId(1);

    tom.setAddressByStudentId(tom_address);
    //tom_address.setStudentByAddressId(tom); //#1
    session.save(tom);
    session.getTransaction().commit();
}

这是我的映射:

<class name="com.model.xmlType.AddressEntity" table="ADDRESS" schema="CHINOOK">
    <id name="addressId">
        <column name="ADDRESS_ID" sql-type="number(10)" precision="10"/>
    </id>
    <property name="city">
        <column name="CITY" sql-type="nvarchar2(50)" length="50"/>
    </property>
    <one-to-one name="studentByAddressId" class="com.model.xmlType.StudentEntity"/>
</class>


<class name="com.model.xmlType.StudentEntity" table="STUDENT" schema="CHINOOK">
    <id name="studentId">
        <column name="STUDENT_ID" sql-type="number(10)" precision="10"/>
    </id>
    <property name="name">
        <column name="NAME" sql-type="nvarchar2(50)" length="50"/>
    </property>
    <property name="age">
        <column name="AGE" sql-type="number(10)" precision="10"/>
    </property>
    <property name="clazz">
        <column name="CLASS" sql-type="nvarchar2(10)" length="10"/>
    </property>
    <one-to-one name="addressByStudentId" class="com.model.xmlType.AddressEntity" cascade="all"/>

实体类

学生:

public class StudentEntity {
    private Integer studentId;
    private String name;
    private Integer age;
    private String clazz;
    private AddressEntity addressByStudentId;

    public Integer getStudentId() {
        return studentId;
    }

    public void setStudentId(Integer studentId) {
        this.studentId = studentId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
       return age;
    }

    public void setAge(Integer age) {
       this.age = age;
    } 

    public String getClazz() {
       return clazz;
    }

    public void setClazz(String clazz) {
       this.clazz = clazz;
    }


    public boolean equals(Object o) {
       if (this == o) return true;
       if (o == null || getClass() != o.getClass()) return false;

       StudentEntity that = (StudentEntity) o;

       if (studentId != null ? !studentId.equals(that.studentId) : that.studentId != null) return false;
       if (name != null ? !name.equals(that.name) : that.name != null) return false;
       if (age != null ? !age.equals(that.age) : that.age != null) return false;
       if (clazz != null ? !clazz.equals(that.clazz) : that.clazz != null) return false;

       return true;
    }

    public int hashCode() {
        int result = studentId != null ? studentId.hashCode() : 0;
        result = 31 * result + (name != null ? name.hashCode() : 0);
        result = 31 * result + (age != null ? age.hashCode() : 0);
        result = 31 * result + (clazz != null ? clazz.hashCode() : 0);
        return result;
    }

    public AddressEntity getAddressByStudentId() {
        return addressByStudentId;
    }

    public void setAddressByStudentId(AddressEntity addressByStudentId) {
       this.addressByStudentId = addressByStudentId;
    }
}

地址:

public class AddressEntity {
    private Integer addressId;
    private String city;
    private StudentEntity studentByAddressId;

    public Integer getAddressId() {
        return addressId;
    }

    public void setAddressId(Integer addressId) {
        this.addressId = addressId;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        AddressEntity that = (AddressEntity) o;

        if (addressId != null ? !addressId.equals(that.addressId) : that.addressId != null) return false;
        if (city != null ? !city.equals(that.city) : that.city != null)   return false;

        return true;
    }

    @Override
    public int hashCode() {
        int result = addressId != null ? addressId.hashCode() : 0;
        result = 31 * result + (city != null ? city.hashCode() : 0);
        return result;
    }

    public StudentEntity getStudentByAddressId() {
        return studentByAddressId;
    }

    public void setStudentByAddressId(StudentEntity studentByAddressId) {
        this.studentByAddressId = studentByAddressId;
    }
}

它的工作非常顺利,两个实体都得到了保存。但是当第1行被取消注释时,只有实体Student才会保存。代码如下:

public static void oneToOneMappingWithXML(Session session) throws Exception {
    StudentEntity tom = new StudentEntity();
    tom.setName("Tom");
    tom.setAge(10);
    tom.setClazz("5B");
    tom.setStudentId(1);

    AddressEntity tom_address = new AddressEntity();
    tom_address.setCity("New York");
    tom_address.setAddressId(1);

    tom.setAddressByStudentId(tom_address);
    tom_address.setStudentByAddressId(tom); //#1
    session.save(tom);
    session.getTransaction().commit();
}

我不知道为什么。那么,有人可以向我解释一下吗?

2 个答案:

答案 0 :(得分:0)

请注意,仅在一侧设置引用时,Hibernate不会自动使对象引用成双向。因此,必须确保在双向引用上,两个方面在保持之前都能正确设置。

尝试将实体看作数据库中的记录而不是对象。如果对象“汤姆”没有“知道”他甚至有一个地址,并且要求“汤姆”坚持自己,那么“汤姆”怎么能坚持他的地址?

(事实上,你可以保存“tom”而没有地址,然后保存一个引用“tom”的地址;然后,如果你重新加载“tom”,他会突然有一个地址,因为数据库中的 ,关系的方向并不重要。但你不应该这样做。)

始终在两侧正确初始化您的双向参考,您应该是好的。

答案 1 :(得分:0)

session.save(tom_address);
session.save(tom);
session.getTransaction().commit();

在保存学生之前保存地址。