我是靠谱客的博主 缓慢哈密瓜,最近开发中收集的这篇文章主要介绍Hibernate之两种一对一关系映射方式,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前言

在前面的Hibernate学习中已经介绍了多对一、一对多、多对多的关系,本文主要介绍一对一关系。比如:一个用户有且仅有一个身份证,一个身份证也只能对应一个用户。而在学习Hibernate框架主要是学习映射关系如何配置。那么一对一关系映射主要有两种配置方式。一种是基于外键的映射关系。一种是基于主键的映射关系。本文将分别从具体案例出发,介绍两种不同的一对一映射配置。

案例说明:

需求
一个用户对应一个身份证信息。即用户与身份证信息。

设计数据库:
这里写图片描述

从数据库的设计发现,上面一种是基于外键的映射关系。主要是将用户的主键user_id作为身份证表的外键字段关联起来,作为单独的外键列,保存在数据库中。不难发现,其实这种
方式并不陌生,类似于一对多的映射关系,多方维护着一方的主键作为外键。所以基于外键映射方式的一对一关系也是特殊的一对多,只是有一个特殊条件,外键必须唯一,限制了唯一性。

下面一种呢,是基于主键的一对一关系映射方式。将用户表的主键user_id作为身份证表的主键,即主键必唯一。但是关联关系怎么保存呢,只能通过外键的方式了,也就是说user_id即是主键也是外键。

案例代码

我们从具体的代码来介绍:
先是第一种基于主键的映射:
User.java

// 用户
public class User {

    private int userId;
    private String userName;
    // 用户与身份证信息, 一对一关系
    private IdCard idCard;


    public IdCard getIdCard() {
        return idCard;
    }
    public void setIdCard(IdCard idCard) {
        this.idCard = idCard;
    }
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }   

}

IdCard.java

// 身份证
public class IdCard {

    // 身份证号(主键)
    private String cardNum;// 对象唯一表示(Object Identified, OID)
    private String place; //  身份证地址
    // 身份证与用户,一对一的关系
    private User user;


    public String getCardNum() {
        return cardNum;
    }
    public void setCardNum(String cardNum) {
        this.cardNum = cardNum;
    }
    public String getPlace() {
        return place;
    }
    public void setPlace(String place) {
        this.place = place;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }


}

这里的user映射文件相对简单,只需要说明userid自增长,有一个userName属性字段,然后《one-to-one》一对一映射关系,指定关系的类型和user类中对应的成员属性名称idCard,其实就是告诉hibernate如何去找关联一方的类和对应的配置文件。

IdCard.hbm.xml

<?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="com.nwpu.geeker.one2one">

    <class name="IdCard" table="t_IdCard">
        <id name="cardNum">
            <generator class="assigned"></generator>
        </id>   
        <property name="place" length="20"></property>

        <!-- 
            一对一映射,有外键方
            unique="true"   给外键字段添加唯一约束
         -->
         <many-to-one name="user" unique="true" column="user_id" class="User" cascade="save-update"></many-to-one>

    </class>


</hibernate-mapping>

注意:因为t_IdCard表中主键为身份证号,必须设置成手动方式,因此在配置主键生成策略时使用“assigned”。因为基于外键的一对一关系也是特殊的一对多关系,在多的一方设置《many-to-one》,记住一点,把对象映射到数据库生成外键字段只能用《many-to-one》配置。
还要注意在配置中给外键字段添加唯一约束即,unique=”true”。

测试保存:App.java

public class App {

    private static SessionFactory sf;
    static {
        sf = new Configuration()
            .configure()
            .addClass(IdCard.class)   
            .addClass(User.class)   // 测试时候使用
            .buildSessionFactory();
    }

    @Test
    public void getSave() {

        Session session = sf.openSession();
        session.beginTransaction();

        // 用户
        User user = new User();
        user.setUserName("Jack");
        // 身份证
        IdCard idCard = new IdCard();
        idCard.setCardNum("121202XXX");
        idCard.setPlace("北京XXX");
        // 关系
        idCard.setUser(user);

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

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

    }

}

因为设置了级联保存,直接保存idCard对象,即可。数据库保存成功!

另外一种基于主键的一对一映射
和上面的方式javaBean和配置有所不同:
User.java

// 用户
public class User {

    private int userId;
    private String userName;
    // 用户与身份证信息, 一对一关系
    private IdCard idCard;


    public IdCard getIdCard() {
        return idCard;
    }
    public void setIdCard(IdCard idCard) {
        this.idCard = idCard;
    }
    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }

}

IdCard .java

// 身份证
public class IdCard {

    private int user_id;
    // 身份证号
    private String cardNum;
    private String place; //  身份证地址
    // 身份证与用户,一对一的关系
    private User user;



    public int getUser_id() {
        return user_id;
    }
    public void setUser_id(int userId) {
        user_id = userId;
    }
    public String getCardNum() {
        return cardNum;
    }
    public void setCardNum(String cardNum) {
        this.cardNum = cardNum;
    }
    public String getPlace() {
        return place;
    }
    public void setPlace(String place) {
        this.place = place;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }


}

注意:因为是基于主键的,因此IdCard 表中必须有主键字段user_id。

配置文件:User.hbm.xml

<?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="com.nwpu.geeker.one2one2">

    <class name="User" table="t_user">
        <id name="userId">
            <generator class="native"></generator>
        </id>   
        <property name="userName" length="20"></property>
        <!-- 
            一对一映射: 没有外键方
         -->
         <one-to-one name="idCard" class="IdCard"></one-to-one>

    </class>


</hibernate-mapping>

和上面user配置文件相同。

IdCard.hbm.xml

<?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="com.nwpu.geeker.one2one2">

    <class name="IdCard" table="t_IdCard">
        <id name="user_id">
            <!-- 
                id 节点指定的是主键映射, 即user_id是主键
                主键生成方式: foreign  即把别的表的主键作为当前表的主键;
                        property (关键字不能修改)指定引用的对象     对象的全名 cn..User、  对象映射 cn.User.hbm.xml、   table(id)
             -->
            <generator class="foreign">
                <param name="property">user</param>
            </generator>
        </id>   
        <property name="cardNum" length="20"></property>
        <property name="place" length="20"></property>

        <!-- 
            一对一映射,有外键方
            (基于主键的映射)
             constrained="true"  指定在主键上添加外键约束
         -->
        <one-to-one name="user" class="User" constrained="true"  cascade="save-update"></one-to-one>

    </class>

</hibernate-mapping>

注意:IdCard表的主键生成策略为引用别的表的主键。因此配置class=”foreign”。还要告诉Hibernate引用的是哪一张表的映射,所以<param name="property">user</param>,其中name=”property”,为必须的不能修改,而user指定为在IdCard.java中定义的成员变量的名字。

还有,基于主键的一对一关系,也是必须有外键关联的。因此还要在《one-to-one》配置constrained=”true”,即指定在主键上添加外键约束。

这里的测试代码,与上面App.java一致,也能保持数据量成功!保持的数据与数据库设计第一幅图一致。

最后

以上就是缓慢哈密瓜为你收集整理的Hibernate之两种一对一关系映射方式的全部内容,希望文章能够帮你解决Hibernate之两种一对一关系映射方式所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(58)

评论列表共有 0 条评论

立即
投稿
返回
顶部