前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hibernate实体关系映射

Hibernate实体关系映射

作者头像
南风
发布2019-04-22 17:16:08
9950
发布2019-04-22 17:16:08
举报
文章被收录于专栏:Java大联盟Java大联盟

前言:

上一篇文章我们学习了Hibernate的框架搭建,并且完成了单表的CRUD操作,今天我们来学习Hibernate中的多表关联。

主要来说最常见的两种关系:一对多关系,多对多关系。

我们写程序就是为了解决现实生活中的问题,所以我们用现实生活中的例子去理解程序就会比较容易。

一对多关系:

生活中常见的一对多关系就是客户和订单的关系,每一个客户可以购买多个产品,生成多个订单,但是一个订单只能属于一个客户,所以客户(Customer)是一,订单(Orders)是多。

这种关系在数据库中如何体现呢?

数据表中一的一方是主表(Customer),多的一方是从表(Orders),通过主外键关联关系来维护这种关系。

从表中的cid为外键,该外键被主表的主键id所约束。

在面向对象的思想中,如何体现这一关系呢?

在面向对象的场景中它们的关系应该是Orders拥有一个Customer对象属性,Customer拥有一个Orders集合属性。

代码语言:javascript
复制
public class Customer {
    private int id;
    private String name;
    private Set<Orders> orders;
    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 Set<Orders> getOrders() {
        return orders;
    }
    public void setOrders(Set<Orders> orders) {
        this.orders = orders;
    }
}
代码语言:javascript
复制
public class Orders {
    private int id;
    private String name;
    private Customer customer;
    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 Customer getCustomer() {
        return customer;
    }
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
}

多对多关系:

大学生选课则是一个典型的多对多关系的体现,我们知道一个学生可以选择多门课程,同时,一门课程也可以被多个学生选择,所以学生(Student)是多,课程(Classes)也是多。

数据库中是通过两个一对多关系来维护这种关系的,即Student表和Classes都是主表,额外增加一张中间表作为从表(Student_Classes),两张主表与中间表之间都是一对多的关系。

中间表(Student_Classes)中的sid和cid均为外键,分别被Student表的id和Classes表的id约束。

在面向对象的场景中它们的关系应该是Student拥有一个Classes集合属性,同时,Classes拥有一个Student集合属性。

代码语言:javascript
复制
public class Student {
    private int id;
    private String name;
    private Set<Classes> classes;
    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 Set<Classes> getClasses() {
        return classes;
    }
    public void setClasses(Set<Classes> classes) {
        this.classes = classes;
    }
}
代码语言:javascript
复制
public class Classes {
    private int id;
    private String name;
    private Set<Student> students;
    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 Set<Student> getStudents() {
        return students;
    }
    public void setStudents(Set<Student> students) {
        this.students = students;
    }
}

好了,解释完一对多和多对多关系,我们会发现Java与数据库完全是两种思维方式来体现这两个关系,Hibernate框架的作用就是将这两种思维方式进行转换和映射。

代码:

通过前面的学习,我们知道Hibernate框架是通过配置实体关系映射文件进行转换的。

一对多:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.southwind.entity">
    <class name="Customer" table="customer">
        <!-- 配置主键映射 -->
        <id name="id" type="java.lang.Integer">
            <column name="id"></column>
            <!-- 设置主键生成方式 -->
            <generator class="native"></generator>
        </id>

        <!-- 配置其他属性 -->
        <property name="name" type="java.lang.String">
            <column name="name"></column>
        </property>

        <set name="orders" table="orders" lazy="extra">
            <!-- 配置外键 -->
            <key column="cid"></key>
            <one-to-many class="Orders"/>
        </set>
    </class>
</hibernate-mapping>

Customer.hbm.xml:

set标签来配置实体类中的集合属性orders; name与实体类属性名对应; table与数据表字段名对应; key与外键字段名对应; one-to-many与集合泛型的实体类对应。

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.southwind.entity">
    <class name="Orders" table="orders">
        <!-- 配置主键映射 -->
        <id name="id" type="java.lang.Integer">
            <column name="id"></column>
            <!-- 设置主键生成方式 -->
            <generator class="native"></generator>
        </id>

        <!-- 配置其他属性 -->
        <property name="name" type="java.lang.String">
            <column name="name"></column>
        </property>

        <many-to-one name="customer" class="Customer" column="cid"></many-to-one>
    </class>
</hibernate-mapping>

Orders.hbm.xml:

many-to-one标签来配置实体类对应的对象属性customer; name与属性名对应; class与属性的所属类对应; column与外键字段名对应。

同时,不要忘记将这两个配置文件添加到hibernate.cfg.xml中。

代码语言:javascript
复制
        <!-- 添加实体关系映射文件 -->
        <mapping resource="com/southwind/entity/Customer.hbm.xml"/>
        <mapping resource="com/southwind/entity/Orders.hbm.xml"/>

接下来就可以调用Hibernate API进行操作了。

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        //1.创建Configuration对象,加载hibernate.cfg.xml
        Configuration configuration = new Configuration();
        configuration = configuration.configure();

        //2.创建ServiceRegistry对象,hibernate.cfg.xml所有配置需要在该对象中进行注册才能生效
        ServiceRegistryBuilder srb = new ServiceRegistryBuilder();
        srb.applySettings(configuration.getProperties());
        ServiceRegistry sr = srb.buildServiceRegistry();

        //3.创建SessionFactory对象
        SessionFactory sessionFactory = configuration.buildSessionFactory(sr);

        //4.创建Session对象
        Session session = sessionFactory.openSession();

        //5.创建Customer对象
        Customer customer = new Customer();
        customer.setName("张三");

        //6.创建Orders对象
        Orders orders = new Orders();
        orders.setName("订单1");

        //7.建立关联关系
        orders.setCustomer(customer);

        //8.保存
        session.save(customer);
        session.save(orders);

        //9.提交事务
        session.beginTransaction().commit();

        //10.关闭session
        session.close();

    }

}

多对多:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.southwind.entity">
    <class name="Classes" table="classes">
        <!-- 配置主键映射 -->
        <id name="id" type="java.lang.Integer">
            <column name="id"></column>
            <!-- 设置主键生成方式 -->
            <generator class="native"></generator>
        </id>

        <!-- 配置其他属性 -->
        <property name="name" type="java.lang.String">
            <column name="name"></column>
        </property>

        <set name="students" table="students_classes">
            <!-- 配置外键 -->
            <key column="cid"></key>
            <many-to-many class="Student" column="sid"></many-to-many>
        </set>
    </class>
</hibernate-mapping>
代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.southwind.entity">
    <class name="Student" table="student">
        <!-- 配置主键映射 -->
        <id name="id" type="java.lang.Integer">
            <column name="id"></column>
            <!-- 设置主键生成方式 -->
            <generator class="native"></generator>
        </id>

        <!-- 配置其他属性 -->
        <property name="name" type="java.lang.String">
            <column name="name"></column>
        </property>

        <set name="classes" table="students_classes">
            <!-- 配置外键 -->
            <key column="sid"></key>
            <many-to-many class="Classes" column="cid"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

Classes.hbm.xml和Student.hbm.xml中都是通过set标签来配置双向关系的:

name是实体类对应的集合属性名, table对应中间表名, key对应中间表的外键字段名, many-to-many与集合泛型的实体类对应,column属性与中间表的外键字段名对应。

将这两个配置文件添加到hibernate.cfg.xml中。

代码语言:javascript
复制
        <!-- 添加实体关系映射文件 -->
        <mapping resource="com/southwind/entity/Customer.hbm.xml"/>
        <mapping resource="com/southwind/entity/Orders.hbm.xml"/>
        <mapping resource="com/southwind/entity/Classes.hbm.xml"/>
        <mapping resource="com/southwind/entity/Student.hbm.xml"/>

调用Hibernate API进行操作。

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        //1.创建Configuration对象,加载hibernate.cfg.xml
        Configuration configuration = new Configuration();
        configuration = configuration.configure();
       
        //2.创建ServiceRegistry对象,hibernate.cfg.xml所有配置需要在该对象中进行注册才能生效
        ServiceRegistryBuilder srb = new ServiceRegistryBuilder();
        srb.applySettings(configuration.getProperties());
        ServiceRegistry sr = srb.buildServiceRegistry();
      
        //3.创建SessionFactory对象
        SessionFactory sessionFactory = configuration.buildSessionFactory(sr);
       
        //4.创建Session对象
        Session session = sessionFactory.openSession();

        //5.创建Classes对象
        Classes classes = new Classes();
        classes.setName("Java");

        //6.创建Student对象
        Student student = new Student();
        student.setName("张三");

        //7.建立关联关系
        Set<Classes> classesSet = new HashSet<Classes>();
        classesSet.add(classes);
        student.setClasses(classesSet);

        //8.保存
        session.save(classes);
        session.save(student);

        //9.提交事务
        session.beginTransaction().commit();

        //10.关闭session
        session.close();
    }

}

总结:

使用Hibernate完成一对多和多对多关系映射,重点是要理解两点:1.数据表中如何维护;2.Java代码中如何维护。搞清楚这两者的区别,就明白了Hibernate框架的用法,使用Hibernate特定的标签进行配置即可。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-01-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java大联盟 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档