2.0、Hibernate-级联关系

news2025/1/31 11:30:40

2.0、Hibernate-级联关系

级联关系 中 最为常见的就是 ->

1、一对多关系 :一个消费者可以购买多个商品 -> 生成多个订单; 消费者是1,订单是多

        那么在数据库中,1 的一方是主表,多的一方是从表,通过主外键关系去维护;

        在Java的面向对象中就是用pojo实体类属性去表示;

2、多对多关系:大学生选课,一个学生可以选择多门课程,一门课程也可以被多个学生选择;

        数据库中是通过两个一对多关系来维护的,学生和课程都是主表,额外增加一张中间表作为从表,两张主表和中间表都是一对多的关系;

        Java 和 数据库 对于这两种关系的体现完全是两种不同的方式,Hibernate 框架的作用就是将这两种方式进行转换和映射;

接下来看看一对多代码演示【环境配置在 1.0、Hibernate-快速入门初体验中介绍过了】:

第一步:数据库中创建两张表 customer 和 orders,如下所示 ->

第二步:在 com.hkl.pojo 文件夹下创建两个 pojo 实体类 Java 文件,customer.java 和 order.java,如下所示->

package com.hkl.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Set;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Customer {
    private Integer id;
    private String name;
//    一个消费者对应多个订单
    private Set<Order> orders;
}
package com.hkl.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
    private Integer id;
    private String name;
    //一个订单对应一个消费者
    private Customer customer;
}

第三步:在 com.hkl.pojo 文件夹下创建两个xml配置文件,Customer.hbm.xml 和 Order.hbm.xml,如下所示->

Customer.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>

    <class name="com.hkl.pojo.Customer" table="customer">
<!--        主键映射,数据库表中的主键字段用 id 配置,而 name = "id" 这个 id 指的是 Customer 实体类中的 id 属性名-->
        <id name="id" type="java.lang.Integer">
<!--            数据库表 id 主键字段配置-->
            <column name="id"></column>
<!--            设置主键自增方式 -> identity-->
            <generator class="identity"></generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="name"></column>
        </property>

<!--        orders是实体类Customer中的属性名,该属性是一个Order类的集合,所以对应表 order-->
        <set name="orders" table="orders">
<!--            这里配置一下主外键 cid -->
            <key column="cid"></key>
<!--            消费者和订单的关系是一对多,所以这里是 one-to-many,然后给set类型加一个对象,对象类型是Order-->
            <one-to-many class="com.hkl.pojo.Order"></one-to-many>
        </set>
    </class>

</hibernate-mapping>

Order.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>

    <class name="com.hkl.pojo.Order" table="orders">
        <!--        主键映射,数据库表中的主键字段用 id 配置,而 name = "id" 这个 id 指的是 Customer 实体类中的 id 属性名-->
        <id name="id" type="java.lang.Integer">
            <!--            数据库表 id 主键字段配置-->
            <column name="id"></column>
            <!--            设置主键自增方式 -> identity-->
            <generator class="identity"></generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="name"></column>
        </property>

<!--        这里订单和消费者是多对一的关系,所以 order 是从表,外键依旧是 cid-->
        <many-to-one name="customer" class="com.hkl.pojo.Customer" column="cid"></many-to-one>
    </class>

</hibernate-mapping>

 说明一下 标签 含义 ->

        set 标签来配置实体类中的集合属性orders;

        name 实体类属性名;

        table 表名;

        key 外键

        one-to-many 与集合泛型的实体类对应;

        many-to-one 配置实体类对应的对象属性;

        name 属性名;

        class 属性对应的类;

        column 外键;

        到这里其实就可以看出来 hibernate 和 mybatis 的区别了,首先 mybatis 是一个半自动的 ORM 框架,而 hibernate 是一个全自动的 ORM 框架;

        hibernate 是将 数据库表 和 pojo实体类 直接映射,而 mybatis 是将 sql结果集 和 pojo实体类 映射起来;

第四步:将这两个映射配置文件 注册 到 hibernate 配置文件中去,代码如下 ->

<!--注册实体关系映射文件-->        
<mapping resource="com/hkl/pojo/Customer.hbm.xml"></mapping>
<mapping resource="com/hkl/pojo/Order.hbm.xml"></mapping>

第五步:用 hibernate API 去调用,在 test 文件夹下创建 Test2.java 文件,如下所示->

import com.hkl.pojo.Customer;
import com.hkl.pojo.Order;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Test2 {
    public static void main(String[] args) {
//        创建configuration
        Configuration configuration = new Configuration().configure();
//        获取sessionFactory
        SessionFactory sessionFactory = configuration.buildSessionFactory();
//        获取Session
        Session session = sessionFactory.openSession();
//        创建Customer
        Customer customer = new Customer();
        customer.setName("小澜");
//        创建 order
        Order order = new Order();
        order.setName("订单1");
//        建立关联关系
        order.setCustomer(customer);
//        保存
        session.save(customer);
        session.save(order);
//        提交事务
        session.beginTransaction().commit();
//        关闭session
        session.close();

    }
}

运行后可以看到数据添加成功->

 

        记录一下这里我遇到的一个问题,一直报错说我的 sql 语句有问题,找了很久才发现数据库的表名是 order,而这个名字是一个sql关键字,所以不能使用,如下所示->

 

多对多代码演示->

第一步:创建数据库表 account 和 course 和 account_course 三张表,如下所示->

 第二步:在 com.hkl.pojo 文件夹下创建对应的 pojo 实体类文件,Account.java 和 Course.java 文件,如下所示->

Account.java

package com.hkl.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Set;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
    private Integer id;
    private String name;
    private Set<Course> courses;
}

 Course.java

package com.hkl.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Set;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Course {
    private Integer id;
    private String name;
    private Set<Account> accounts;
}

 

第三步:在 com.hkl.pojo文件夹下创建两个对应的映射文件,Account.hbm.xml 和 Course.hbm.xml ,如下所示->

Account.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>

    <class name="com.hkl.pojo.Account" table="t_account">
        <!--        主键映射,数据库表中的主键字段用 id 配置,而 name = "id" 这个 id 指的是 Course 实体类中的 id 属性名-->
        <id name="id" type="java.lang.Integer">
            <!--            数据库表 id 主键字段配置-->
            <column name="id"></column>
            <!--            设置主键自增方式 -> identity-->
            <generator class="identity"></generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="name"></column>
        </property>

        <!--courses是实体类Course中的属性名,该属性是一个 Course 类的集合,所以对应表 account_course-->
        <set name="courses" table="account_course">
            <!--这里配置一下主外键 cid -->
            <key column="aid"></key>
            <!--学生和选课的关系是多对多,所以这里是 many-to-many,然后给set类型加一个对象,对象类型是Account , column是account在这个中间表中的外键aid-->
            <many-to-many class="com.hkl.pojo.Course" column="cid"></many-to-many>
        </set>
    </class>

</hibernate-mapping>

Course.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>

    <class name="com.hkl.pojo.Course" table="t_course">
        <!--        主键映射,数据库表中的主键字段用 id 配置,而 name = "id" 这个 id 指的是 Account 实体类中的 id 属性名-->
        <id name="id" type="java.lang.Integer">
            <!--            数据库表 id 主键字段配置-->
            <column name="id"></column>
            <!--            设置主键自增方式 -> identity-->
            <generator class="identity"></generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="name"></column>
        </property>

        <!--courses是实体类Course中的属性名,该属性是一个 Course 类的集合,所以对应表 account_course-->
        <set name="accounts" table="account_course">
            <!--这里配置一下主外键 aid -->
            <key column="cid"></key>
            <!--学生和选课的关系是多对多,所以这里是 many-to-many,然后给set类型加一个对象,对象类型是Course , column是course在这个中间表中的外键cid-->
            <many-to-many class="com.hkl.pojo.Account" column="aid"></many-to-many>
        </set>
    </class>

</hibernate-mapping>

 

第四步:将映射文件注册到 hibernate.cfg.xml 配置文件中,如下所示->

<mapping resource="com/hkl/pojo/Account.hbm.xml"></mapping>
<mapping resource="com/hkl/pojo/Course.hbm.xml"></mapping>

 

第五步:在test文件夹下创建 test3.java 文件,调用 Hibernate API 去测试一下,如下所示->

import com.hkl.pojo.Account;
import com.hkl.pojo.Course;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import java.util.HashSet;
import java.util.Set;

public class Test3 {
    public static void main(String[] args) {
        //        创建configuration
        Configuration configuration = new Configuration().configure();
//        获取sessionFactory
        SessionFactory sessionFactory = configuration.buildSessionFactory();
//        获取Session
        Session session = sessionFactory.openSession();
        //创建course
        Course course = new Course();
        course.setName("Java编程与设计");
        //创建account
        Account account = new Account();
        account.setName("小澜");
        //将封装好的course放到set集合中去
        Set<Course> courses = new HashSet<Course>();
        courses.add(course);
        //将封装好的set集合与account建立联系
        account.setCourses(courses);
        //提交事务
        session.save(course);
        session.save(account);
        //提交事务
        session.beginTransaction().commit();
        //关闭session
        session.close();
    }
}

可以看到我这里运行了三次都成功的添加了数据~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/104760.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C# Winform 三层架构

一、介绍 三层架构是 C# 桌面开发中比较常用的框架&#xff0c;是由 表示层&#xff08;UI&#xff09;、业务逻辑层&#xff08;BLL&#xff09;和数据访问层&#xff08;DAL&#xff09;三层架构组成&#xff0c;目的是为了 “高内聚&#xff0c;低耦合”。开发人员分工更明…

深度学习入门(六十五)循环神经网络——序列到序列学习(seq2seq)

深度学习入门&#xff08;六十五&#xff09;循环神经网络——序列到序列学习&#xff08;seq2seq&#xff09;前言循环神经网络——序列到序列学习&#xff08;seq2seq&#xff09;课件机器翻译seq2seq编码器-解码器细节训练衡量生成序列的好坏的BLEU总结教材1 编码器2 解码器…

为什么世界500强企业都要求员工必须学Python编程语言?

行业的更迭与进化并非虚无缥缈&#xff0c;它就发生在我们每天的生活中。当代最具竞争力的技能是什么&#xff1f;高盛、JP 摩根、麦肯锡等顶级公司纷纷给出了答案——编程。 今年新加入摩根大通的全部资产管理分析师必须强制学习编程语言&#xff0c;Python。 摩根大通资产管…

【Java异常】处理异常

一&#xff1a;异常的处理&#xff1a;抓抛处理 过程一&#xff1a;"抛":程序在正常执行的过程中&#xff0c;一旦出现异常&#xff0c;就会在异常代码处生成一个对应异常类的对象并将此对象抛出一旦抛出对象以后&#xff0c;其后的代码不再执行 过程二&#xff1a;&…

科班演员陶弈菱:北京电影学院的系统学习是我艺术道路上最大的底气

今天的记忆是带着海水的味道………”12月18日&#xff0c;在年末岁尾之际&#xff0c;徽风皖韵熏陶下成长的新生代演员陶奕菱再次来到海南三亚&#xff0c;受邀参加第四届海南岛国际电影节&#xff0c;迫不及待地跑向沙滩面朝大海&#xff0c;感受多姿多彩的魅力三亚。 优雅端…

在 React 中应用设计模式:策略模式

这篇文章是关于我们许多人在 React 和前端开发中遇到的一个问题&#xff08;有时甚至没有意识到这是一个问题&#xff09;&#xff1a;在不同的组件、钩子、实用程序等中实现了一段逻辑。 让我们深入了解问题的详细信息以及如何解决它。正如标题所暗示的&#xff0c;我们将使用…

DPDK-收包完整过程

本篇博客作为自己了解dpdk收包过程的一个记录。在写时发现已经有很多写DPDK收包过程的博客了&#xff0c;但还是决定自己写一遍。 DPDK收包分为两个阶段&#xff0c;首先是DMA将数据包从网卡搬运到内存&#xff0c;然后是调用dpdk提供的接口rte_eth_rx_burst去取。但是具体是怎…

Oracle和其他数据库有什么区别?从引号开始了解!

无论测试或者开发&#xff0c;对数据库的增删改查都是家常便饭。但有些小知识是经常被忽略&#xff0c;却又不能不去了解的&#xff0c;例如单引号和双引号的用法和区别&#xff0c;看完这一篇&#xff0c;你肯定会有收获。 首先我们要区别一个概念&#xff0c;即单引号(‘)和…

【Java语言】— Java基础02

1.数据类型 &#xff08;1&#xff09;数据类型的作用 数据类型就是约束变量存储数据的形式。 数据类型 变量名称初始值;&#xff08;2&#xff09;数据类型的分类 引用数据类型&#xff08;除基本数据类型之外的&#xff0c;如String&#xff09;基本数据类型:4大类8种。 …

如何从 0 开始学 Python 自动化测试开发(一)

本文是「如何从 0 开始学 Python 自动化测试开发」专题系列文章第一篇&#xff0c;适合零基础入门的同学。 作者方程老师&#xff0c;是前某跨国通信公司高级测试经理&#xff0c;目前为某互联网名企资深测试技术专家&#xff0c;也是霍格沃兹测试学院特邀讲师。有十余年大型电…

项目管理软件怎么选?只需要关注4点

项目管理有许多不同的风格&#xff0c;但无论如何管理项目&#xff0c;根据企业的当前需求和未来发展轨迹选择合适的项目管理软件都很重要。 虽然大多数优秀的项目管理软件都提供相似的功能&#xff0c;但没有两个平台是完全相同的。以下是企业在选择项目管理软件时应该考虑的…

【虹科新闻】虹科与SOSLAB正式建立合作伙伴关系

近日&#xff0c;虹科与SOSLAB正式建立合作伙伴关系&#xff0c;虹科将共同与SOSLAB开展亚太地区市场开发&#xff0c;聚焦于工业领域客户开拓&#xff0c;深入本地技术支持、测试与售后服务落地&#xff0c;为客户提供高效、可靠的激光雷达解决方案。 “虹科很高兴与SOSLAB合作…

锁等待超时

问题背景 今天测试同事发现项目里面大部分接口报错&#xff0c;把日志捞出来看了下出现大量的锁等待超时的错误。 Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transactionat sun.reflect.N…

MULLS: Versatile LiDAR SLAM via Multi-metric Linear Least Square论文阅读

1. 摘要 随着自动驾驶与移动建图的快速发展&#xff0c;实际项目中对现成的激光SLAM建图方案的需求也越来越强烈&#xff0c;并且要求解决方案适用于各种不同规格的激光雷达与各种复杂场景。因此&#xff0c;我们提出了MULLS&#xff0c;一种高效&#xff0c;低漂移&#xff0…

状态观测控制器设计与仿真验证

【无限嚣张&#xff08;菜菜&#xff09;】&#xff1a;hello您好&#xff0c;我是菜菜&#xff0c;很高兴您能来访我的博客&#xff0c;我是一名爱好编程学习研究的菜菜&#xff0c;每天分享自己的学习&#xff0c;想法&#xff0c;博客来源与自己的学习项目以及编程中遇到问题…

深度学习炼丹-数据处理和增强

前言一&#xff0c;Normalization 概述 1.1&#xff0c;Normalization 定义1.2&#xff0c;什么情况需要 Normalization1.3&#xff0c;Data Normalization 方法1.4&#xff0c;示例代码 二&#xff0c;normalize images 2.1&#xff0c;图像 normalization 定义2.2&#xff0c…

[XCTF]halo(2019护网杯)(难度2)

目录 前言 一、题目重述 二、解题思路 1.Base64解密 2.难以想到的异或运算 三、flag 总结 前言 注意&#xff01;攻防世界题目有误&#xff01;&#xff01;给出题目与原题不一样但是答案却和护网杯原题答案一样&#xff01;&#xff01; 一、题目重述 aWdxNDs0NDFSOz…

NVM Express Base Specification 2.0c - 2 Theory of Operation

The interface has the following key attributes: 在命令提交或完成路径中不需要非缓存/ MMIO寄存器读取;在命令提交路径中最多需要一个MMIO寄存器写或一个64B消息;支持多达65,535个I/O队列&#xff0c;每个I/O队列支持多达65,535个未完成的命令;优先级与每个I/O队列相关联&a…

【MySQL】基于InnoDB的数据库索引

文章目录前言1、索引引入2、索引语法2.1、创建索引2.2、查看索引2.3、删除索引2.4、案例引入3、索引结构3.1、概述3.2、引擎支持3.3、BTree3.4、Hash4、索引类别4.1、分类4.2、过程分析5、性能分析5.1、执行频率5.2、慢查询日志5.3、explain6、最左前缀原则7、索引失效7.1、范围…

2023年学一门IT技术的最佳选择就是软件测试!

互联网行业的不断发展&#xff0c;也增加了IT行业的就业机会&#xff0c;作为最适合零基础小白入行、门槛低的软件测试岗位来说&#xff0c;也受到越来越多转行者的关注&#xff0c;但是耳边依然充斥着各种关于这个行业不好的言论&#xff0c;诸如“行业饱和了&#xff0c;学完…