Hibernate (八)一对一 (外键关联方式)

一对一 映射有两种方式:
主键关联: id 对应 id 两个主键必须相同
外键关联: id 对应 xxxid 专门设置一个外键属性 (推荐使用)

外键关联方式

例如:下面的例子IdCard 表会有一个专门的外键属性 personId 对应 person 主键id

IdCard.java

public class IdCard {
    private Integer id;
    private String number;
    private Person person; // 关联的公民

IdCard.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="cn.itcast.i_hbm_oneToOne">
    <class name="IdCard" table="idCard">
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="number"/>
        <!-- person属性,Person类型。
            表达的是本类与Person的一对一。
            采用基于外键的一对一映射方式,本方有外键方。 -->
        <many-to-one name="person" class="Person" column="personId" unique="true"></many-to-one>
    </class>
</hibernate-mapping>

Person.java

public class Person {
    private Integer id;
    private String name;
    private IdCard idCard; // 关联的身份证

Person.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="cn.itcast.i_hbm_oneToOne">
    <class name="Person" table="person">
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name"/>

        <!-- idCard属性,IdCard类型。
            表达的是本类与IdCard的一对一。
            采用基于外键的一对一映射方式,本方无外键方。
            property-ref属性:
                写的是对方映射中外键列对应的属性名。  
         -->
        <one-to-one name="idCard" class="IdCard" property-ref="person"/>
    </class>
</hibernate-mapping>

第二种方式:

主键关联

其他一样只是,映射文件不同
IdCard.hbm.xml

... ...
<hibernate-mapping package="cn.itcast.i_hbm_oneToOne2">

    <class name="IdCard" table="idCard2">
        <id name="id">
            <!-- 当使用基于主键的一对一映射时,
                有外键方的主键生成策略一定要是foreign。
                参数property:
                    生成主键值时所根据的对象。
             -->
            <generator class="foreign">
                <param name="property">person</param>
            </generator>
        </id>
        <property name="number"/>

        <!-- person属性,Person类型。
            表达的是本类与Person的一对一。
            采用基于主键的一对一映射方式,本方有外键方。 -->
        <one-to-one name="person" class="Person" constrained="true"></one-to-one>
    </class>

</hibernate-mapping>

Person.hbm.xml

... ...
<hibernate-mapping package="cn.itcast.i_hbm_oneToOne2">
    <class name="Person" table="person2">
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name"/>

        <!-- idCard属性,IdCard类型。
            表达的是本类与IdCard的一对一。
            采用基于主键的一对一映射方式,本方无外键方。
         -->
        <one-to-one name="idCard" class="IdCard"></one-to-one>
    </class>
</hibernate-mapping>

测试代码

package cn.itcast.i_hbm_oneToOne;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App {

    private static SessionFactory sessionFactory = new Configuration()//
            .configure()//
            .addClass(Person.class)// 添加Hibernate实体类(加载对应的映射文件)
            .addClass(IdCard.class)// 添加Hibernate实体类(加载对应的映射文件)
            .buildSessionFactory();

    // 保存,有关联关系
    @Test
    public void testSave() throws Exception {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // --------------------------------------------

        // 新建对象
        Person person = new Person();
        person.setName("张三");

        IdCard idCard = new IdCard();
        idCard.setNumber("100000011X");

        // 关联起来
        // person.setIdCard(idCard);
        idCard.setPerson(person);

        // 保存
        session.save(person);
        session.save(idCard);

        // --------------------------------------------
        session.getTransaction().commit();
        session.close();
    }

    // 获取,可以获取到关联的对方
    @Test
    public void testGet() throws Exception {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // --------------------------------------------

        // 获取一方,并显示另一方信息
        // Person person = (Person) session.get(Person.class, 1);
        // System.out.println(person);
        // System.out.println(person.getIdCard());

        IdCard idCard = (IdCard) session.get(IdCard.class, 1);
        System.out.println(idCard);
        System.out.println(idCard.getPerson());

        // --------------------------------------------
        session.getTransaction().commit();
        session.close();

    }

    // 解除关联关系:一对一中,只能有外键方可以维护关联关系。
    @Test
    public void testRemoveRelation() throws Exception {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // --------------------------------------------

        // 从有外键方解除关系,可以。
        // IdCard idCard = (IdCard) session.get(IdCard.class, 1);
        // idCard.setPerson(null);

        // 从无外键方解除关系,不可以。
        Person person = (Person) session.get(Person.class, 1);
        person.setIdCard(null);

        // --------------------------------------------
        session.getTransaction().commit();
        session.close();
    }

    // 删除对象,对关联对象的影响
    @Test
    public void testDelete() throws Exception {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // --------------------------------------------

        // a, 如果没有关联的对方:能删除。
        // b, 如果有关联的对方且可以维护关联关系(有外键方),他就会先删除关联关系,再删除自己。
        // c, 如果有关联的对方且不能维护关联关系(无外键方),所以会直接执行删除自己,就会有异常。

        IdCard idCard = (IdCard) session.get(IdCard.class, 1);
        session.delete(idCard);

        // Person person = (Person) session.get(Person.class, 1);
        // session.delete(person);

        // --------------------------------------------
        session.getTransaction().commit();
        session.close();
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值