Hibernate关联映射-----一对一关联

一对一关联有两种关联方式,即:主键关联和外键关联。

下面将分别对这两种情况进行演示和讨论。在讨论前,首先给出这次用到得POJO,和相应的映射文件的主要片段。

Member类:

public class Member {
    private String id;
    private String name;
    private Integer age;
    private IdCard card;

.......

}

IdCard类:

public class IdCard {
    private String id;
    private String num;
    private Member member;

........

}

先对这两个类解释一下,Member类代表人员,IdCard类代表了身份证,这在现实中也是一对一的关系。

1、主键关联

Member. hbm.xml的主要片段如下:

<hibernate-mapping package="org.louis.domain">
    <class name="Member" table="TEST_MEMBER">
        <id name="id" column="ID">
            <generator class="uuid.hex"></generator>
        </id>
        <property name="age" column="AGE"></property>
        <property name="name" column="NAME"></property>
       
       <one-to-one name="card" class="IdCard" cascade="all"></one-to-one>


.........

</hibernate-mapping>  

IdCard.hbm.xml的配置如下:

<hibernate-mapping package="org.louis.domain">
    <class name="Order" table="TEST_ORDER">
        <id name="id" column="ID">
            <generator class="foreign"><!--使用主键关联,引用Member对应表的主键作为自己的主键-->
                <param name="property">member</param><!--此处的member必须和下面配置的one-to-one的name
属性一样 -->
            </generator>
        </id>
        <property name="num" column="NUM"></property>
       
        <one-to-one name="member" class="Member" constrained="true"></one-to-one>
    </class>
</hibernate-mapping>          

至此,所有的配置工作已经完成。

测试进行测试:

a、新增数据

public void insert(){
        Session session = HibernateSessionFactory.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Member m = new Member();
        m.setAge(24);
        m.setName("Louis");
   
        IdCard card = new IdCard();
        card.setNum("123456789");
        card.setMember(m);//设置Member和IdCard关系,以便IdCard可以从Member取得主键值
       
        m.setCard(card);//设置Member和IdCard关系
       
        session.save(m);
        session.getTransaction().commit();
    }

后台Hibernate执行的SqlServer语句是:

Hibernate: insert into TEST_MEMBER (AGE, NAME, ID) values (?, ?, ?)
Hibernate: insert into TEST_IDCARD (NUM, ID) values (?, ?)

保存IdCard时使用IdCard对象中member对象的Id来为自己的Id赋值的。你现在可以查看数据库,里面两个表的主键值相同。

b、加载数据

public void getMemberById(String id){
        Session session = HibernateSessionFactory.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Member m = (Member)session.load(Member.class, id);
        System.out.println(m);
        session.getTransaction().commit();
    }

后台Hibernate执行的Sql语句是:

    select
        member0_.ID as ID5_1_,
        member0_.AGE as AGE5_1_,
        member0_.NAME as NAME5_1_,
        idcard1_.ID as ID4_0_,
        idcard1_.NUM as NUM4_0_
    from
        TEST_MEMBER member0_
    left outer join
        TEST_IDCARD idcard1_
            on member0_.ID=idcard1_.ID
    where
        member0_.ID=?

可以看出默认采用的左外连接 的查询。

如果把Member.hbm.xml中做些改动如:

<one-to-one name="card" class="IdCard" fetch="select" cascade="all"></one-to-one>

再次执行查询Sql语句如下:

Hibernate:
    select
        member0_.ID as ID5_0_,
        member0_.AGE as AGE5_0_,
        member0_.NAME as NAME5_0_
    from
        TEST_MEMBER member0_
    where
        member0_.ID=?
Hibernate:
    select
        idcard0_.ID as ID4_0_,
        idcard0_.NUM as NUM4_0_
    from
        TEST_IDCARD idcard0_
    where
        idcard0_.ID=?

可以看出生成了两条SQL语句,明显要比一条的性能低一些。

c、删除操作

Hibernate:
    select
        member0_.ID as ID5_0_,
        member0_.AGE as AGE5_0_,
        member0_.NAME as NAME5_0_
    from
        TEST_MEMBER member0_
    where
        member0_.ID=?
Hibernate:
    select
        idcard0_.ID as ID4_0_,
        idcard0_.NUM as NUM4_0_
    from
        TEST_IDCARD idcard0_
    where
        idcard0_.ID=?

Hibernate:
    delete
    from
        TEST_IDCARD
    where
        ID=?
Hibernate:
    delete
    from
        TEST_MEMBER
    where
        ID=?

前两条Sql语句是加载Member和关联的IdCard对象。由于在测试加载数据时改变了抓取数据方式为fetch="select"所以生成了两条,如果改为默认(fetch="join")则只生成一条,并且采用的是左外连接方式。在删除代码中,我只是删除了Member,但是查看数据库和后台的SQL语句看出也把IdCard数据删除了,这是因为我在Member.hbm.xml中的<one-to-one>设置了cascade="all"。如果不设置(默认为“none”),则只会删除Member对象,而不会级联删除IdCard对象。

注意:在这个例子中,一定要注意添加数据、删除数据的先后顺序。添加数据必须先添加Member(因为IdCard的主键由Member而来),删除数据必须先删除IdCard(因为在IdCard.hbm.xml中设置了constrained="true"而使得两个表之间有了约束)。

2、外键关联

使用外键关联,我们还是使用这两个POJO类,只是其映射文件有所调整。调整后的映射文件如下:

Member.hbm.xml :

<hibernate-mapping package="org.louis.domain">
    <class name="Member" table="TEST_MEMBER">
        <id name="id" column="ID">
            <generator class="uuid.hex"></generator>
        </id>
        <property name="age" column="AGE"></property>
        <property name="name" column="NAME"></property>
       
        <one-to-one name="card" class="IdCard" fetch="join" cascade="all" property-ref="member"></one-to-one>

        ......

</hibernate-mapping>

IdCard.hbm.xml :

<hibernate-mapping package="org.louis.domain">
    <class name="IdCard" table="TEST_IDCARD">
        <id name="id" column="ID">
            <generator class="uuid.hex">
            </generator>
        </id>
        <property name="num" column="NUM"></property>
       
        <many-to-one name="member" class="Member" unique="true" column="MEMBER_ID"></many-to-one>
    </class>
</hibernate-mapping>    

依然采用上面的测试代码进行测试:

a、插入数据

后台Hibernate执行的SQL语句

Hibernate:
    insert
    into
        TEST_MEMBER
        (AGE, NAME, ID)
    values
        (?, ?, ?)
Hibernate:
    insert
    into
        TEST_IDCARD
        (NUM, MEMBER_ID, ID)
    values
        (?, ?, ?)

IdCard的外键来自Member的主键。

b、加载数据

同上

c、删除数据

同上

 

至此,一对一的关联关系基本上说的差不多了,下一章将讨论一对多的关联关系。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值