Hibernate - relational mapping one-to-one

one-to-one relationship mapping

One-to-one based on primary key

One-to-one based on the primary key means: for the slave table, its primary key is its foreign key. Then this one-to-one relationship is very clear.

Classic case: Person <–> ID card, Person's id is also IDCard's id

write picture description here

We build projects HibernateOneToOnefor testing.

The two domain objects and their mapping files are as follows:

  • PersonObjects and mapping files:
package com.gavin.domain;

import java.io.Serializable;

public class Person implements Serializable{
    private int id;
    private String name;
    private IDCard idCard;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    public IDCard getIdCard() {
        return idCard;
    }

    public void setIdCard(IDCard idCard) {
        this.idCard = idCard;
    }
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD//EN"
        "http://hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.gavin.domain">
    <class name="com.gavin.domain.Person" table="person" schema="hibernate">
        <id name="id" column="id" type="java.lang.Integer">
            <generator class="increment"/>
        </id>
        <property name="name" column="name" length="64" type="java.lang.String"/>
        <!--这里配置Person和IdCard属性是一对一的关系-->
        <one-to-one name="idCard"/>
    </class>
</hibernate-mapping>
  • IDCardObject and its mapping file:
package com.gavin.domain;

import java.io.Serializable;
import java.util.Date;

public class IDCard implements Serializable {
    private int id;
    private Date validateTime;
    private Person person;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Date getValidateTime() {
        return validateTime;
    }

    public void setValidateTime(Date validateTime) {
        this.validateTime = validateTime;
    }

    public Person getPerson() {
        return person;
    }

    public void setPerson(Person person) {
        this.person = person;
    }
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD//EN"
        "http://hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.gavin.domain.IDCard" table="idcard" schema="hibernate">
        <id name="id" type="java.lang.Integer" column="id">
            <!--因为IDCard的主键是引用Person的主键,故这里采用外键策略-->
            <generator class="foreign">
                <!--这里的值是跟哪一个domain属性一对一-->
                <param name="property">person</param>
            </generator>
        </id>
        <property name="validateTime" column="validateTime" type="java.util.Date"/>
        <one-to-one name="person" constrained="true"/>
    </class>
</hibernate-mapping>

It should be noted here that in the IDCard mapping file, the generation strategy of the primary key ID must be adopted foreign. In addition, one-to-one must be set constrained='true', and the corresponding database table idcard can generate foreign key relationships, otherwise foreign keys will not be generated. This conclusion can also be seen from the SQL statement generated by Hibernate.

  • The test code is as follows:
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();

Person person = new Person();
person.setName("小明");
IDCard idCard = new IDCard();
idCard.setValidateTime(new Date());

// 表明idCard对象是属于person这个对象的
idCard.setPerson(person);
// 这样是不行的,因为是是IDCard关联Person,所以只能idCard.setPerson(person)
// person.setIdCard(idCard);

// 最好先保存Person,再保存idCard
session.save(person);
session.save(idCard);

transaction.commit();
  • The SQL statement generated by Hibernate is as follows:
Hibernate: drop table if exists idcard
Hibernate: drop table if exists person
Hibernate: create table idcard (id integer not null, validateTime datetime, primary key (id)) engine=MyISAM
Hibernate: create table person (id integer not null, name varchar(64), primary key (id)) engine=MyISAM
Hibernate: alter table idcard add constraint FK4opm8ny1jtp2g518o4ktymcne foreign key (id) references person (id)
Hibernate: select max(id) from person
Hibernate: insert into person (name, id) values (?, ?)
Hibernate: insert into idcard (validateTime, id) values (?, ?)
  • The database table structure is as follows:

write picture description here

One-to-one based on foreign keys

Based on the one-to-one foreign key, the ID of Person is different from the ID of IDCard. At this time, IDCard adds a column of pid to associate the ID of Person with the foreign key to form a one-to-one relationship.

write picture description here

So there is a question here. As shown in the figure above, how can foreign keys ensure a one-to-one relationship without duplication? (If no additional constraints are added, a Person can be associated with two IDCards at the same time)

The solution to this problem is: the pid in IDCard has a foreign key constraint, as well as a unique constraint, to ensure that the pid is also unique in the IDCard table.


In the one-to-one relationship based on the foreign key, the domain object is the same as the one-to-one based on the primary key, but the relationship mapping file of the object corresponding to the table needs to be changed.

That is, the IDCard.hbm.xml file here is slightly modified.

In fact, the one-to-one relationship here is just a special case of many-to-one, because without constraints, a Person can correspond to multiple IDCards, so here we add a many-to-one relationship to IDCards, but we need to Add unique='true'the constraints, so as to meet our requirements.

  • IDCard.hbm.xml is modified as follows:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD//EN"
        "http://hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.gavin.domain.IDCard" table="idcard" schema="hibernate">
        <id name="id" type="java.lang.Integer" column="id">
            <generator class="assigned"/>
        </id>
        <property name="validateTime" column="validateTime" type="java.util.Date"/>
        <many-to-one name="person" column="pid" unique="true"/>
    </class>
</hibernate-mapping>

It can be seen that there are two changes, one is the generation strategy of the primary key ID, which has been foreignchanged from the previous one assigned; the other is what is configured here many-to-one, but uniqueconstraints are added.

  • The test method needs to manually set the ID Card's id number, as follows:
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();

Person person = new Person();
person.setName("小明");
IDCard idCard = new IDCard();
idCard.setId(101010);
idCard.setValidateTime(new Date());

// 表明idCard对象是属于person这个对象的
idCard.setPerson(person);
// 这样是不行的,因为是是IDCard关联Person,所以只能idCard.setPerson(person)
//        person.setIdCard(idCard);

session.save(person);
session.save(idCard);

transaction.commit();
  • The SQL statement generated by Hibernate is:
Hibernate: drop table if exists idcard
Hibernate: drop table if exists person
Hibernate: create table idcard (id integer not null, validateTime datetime, pid integer, primary key (id)) engine=MyISAM
Hibernate: create table person (id integer not null, name varchar(64), primary key (id)) engine=MyISAM
Hibernate: alter table idcard add constraint UK_p21bt5txra8q5jmfpvq8kv2h unique (pid)
Hibernate: alter table idcard add constraint FKq0b0d1t0ol6vj0bfoam5f44eb foreign key (pid) references person (id)
Hibernate: select max(id) from person
Hibernate: insert into person (name, id) values (?, ?)
Hibernate: insert into idcard (validateTime, pid, id) values (?, ?, ?)

You can see that the idcard table has an additional column of pids, and foreign key constraints and unique constraints have been added.

  • The resulting table structure is as follows:

write picture description here

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325655197&siteId=291194637