Hibernate第四篇【集合映射、一对多和多对一】

前言

前面的我们使用的是一个表的操作,但我们实际的开发中不可能只使用一个表的…因此,本博文主要讲解关联映射

集合映射

需求分析:当用户购买商品,用户可能有多个地址。

数据库表

我们一般如下图一样设计数据库表,一般我们不会在User表设计多个列来保存地址的。因为每个用户的地址个数都不一的,会造成数据冗余

  • 创建两张数据表,一张保存着用户的信息,一张保存着地址的信息。地址表使用外键来引用用户表

这里写图片描述

实体

由于地址只是使用String类型来保存着,那么我们直接使用一个User对象就可以了


public class User {

    private String id;
    private String username;
    private String password;
    private Set<String> address;

    //各种setter和getter

映射文件


<?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">

<!--在domain包下-->
<hibernate-mapping package="zhongfucheng.domain">

    <class name="User" table="user">

        <!--主键映射-->
        <id name="id" column="id" >
            <generator class="native"/>
        </id>

        <!--普通字段映射-->
        <property name="username" column="username"></property>
        <property name="password" column="password"></property>

        <!--
             Set:
                name: 映射集合的名称
                table:集合的属性要映射到哪张表(address)
             key:
                column:指定要映射的表(address)中的外键列
                element:要映射的表的其他字段
                    类型一定要指定!
        -->
        <set name="address" table="address">
            <key column="user_id"></key>
            <element column="addr" type="string"></element>
        </set>


    </class>
</hibernate-mapping>

测试


package zhongfucheng.domain;

import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

/**
 * Created by ozc on 2017/5/6.
 */
public class App {
    public static void main(String[] args) {

        //创建对象

        User user = new User();
        user.setUsername("123");
        user.setPassword("1234");
        user.getAddress().add("广州");


        //获取加载配置管理类
        Configuration configuration = new Configuration();

        //加载User的映射文件!
        configuration.configure().addClass(User.class);

        //创建Session工厂对象
        SessionFactory factory = configuration.buildSessionFactory();

        //得到Session对象
        Session session = factory.openSession();

        //使用Hibernate操作数据库,都要开启事务,得到事务对象
        Transaction transaction = session.getTransaction();

        //开启事务
        transaction.begin();

        session.save(user);
        //提交事务
        transaction.commit();

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

这里写图片描述


List集合映射配置

既然我们现在已经会了如何配置Set集合了,List集合又怎么配置呢??

想一下,List集合和Set集合有什么区别…List集合是有序的,因此要多配置一个列来维护数据的有序性!

        <list name="address" table="address">
            <key column="user_id"></key>

            <!--index是关键字,不能使用!!!!-->
            <list-index column="index"></list-index>
            <element column="addr" type="string"></element>
        </list>

Map集合映射配置

Map集合和Collection集合的区别就是键值对模型,那么在配置的时候多一个key即可!


        <map name="address" table="address">
            <key column="user_id"  ></key>
            <map-key type="string" column="short"></map-key>
            <element type="string" column="addr"></element>
        </map>

这里写图片描述


一对多和多对一

上面我们讲解了集合映射是怎么配置的,那集合装载的元素有没有可能是对象呢??而不是简单的String类型..那个就太多了!一般地,我们集合装载的都是对象,而不是简单的String,如果我们的装载在集合的数据有很多类型,那么String就不能用了!…

需求:部门与员工之间的关系

  • 一个部门有多个员工; 【一对多】
  • 多个员工,属于一个部门 【多对一】

设计数据库表

员工表应该使用一个外键来记住部门表。这样才可以维护员工和部门之间的关系

这里写图片描述

设计实体

部门实体要使用一个集合来记住所有的员工,员工要使用一个对象引用着部门

这里写图片描述

  • Dept.java
package zhongfucheng.domain;

import java.util.HashSet;
import java.util.Set;

/**
 * Created by ozc on 2017/5/6.
 */
public class Dept {
    private int id ;

    private Set<Employee> set = new HashSet<>();

    private String deptName;

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public Set<Employee> getSet() {
        return set;
    }

    public void setSet(Set<Employee> set) {
        this.set = set;
    }
}

  • Employee.java

package zhongfucheng.domain;

/**
 * Created by ozc on 2017/5/6.
 */
public class Employee {


    private int id;
    private String empName;
    private double salary;
    private Dept dept;

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
}

映射分析

我们在写映射配置文件之前,分析一下怎么写。以部门映射配置文件为例…

现在使用了一个Set集合来维护与员工的关系,Set集合的类型是员工对象…因此在映射文件中需要以下几点

  • 映射集合属性的名称(employees)
  • 映射集合对应的数据表(employee)
  • 对应的数据表的外键字段(dept_id)
  • 集合中的元素类型(Employee)【通过这个类型,Hibernate就可以找到对应类型的映射文件,从而得到对应的信息!】

这里写图片描述

部门映射配置文件


<?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">

<!--在domain包下-->
<hibernate-mapping package="zhongfucheng.domain">

    <class name="Dept" table="dept">
        <id column="id" name="id">
            <generator class="native">

            </generator>
        </id>

        <!--普通字段映射-->
        <property name="deptName" column="deptname"></property>

        <!--维护关系的是Set集合,对应employee表-->
        <set  cascade="save-update" name="set" table="employee">

            <!--employee的外键列是dept_no-->
            <key column="dept_no"></key>

            <!--一个部门对应多个员工,集合的类型是Employee-->
            <one-to-many class="Employee" ></one-to-many>
        </set>
    </class>

</hibernate-mapping>

员工映射配置文件


<?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">

<!--在domain包下-->
<hibernate-mapping package="zhongfucheng.domain">

    <class name="Employee" table="employee">
        <id column="id" name="id">
            <generator class="native">

            </generator>
        </id>

        <!--普通字段数据-->
        <property name="empName" column="empName"></property>
        <property name="salary" column="salary"></property>

        <!--Hibernate这个标签可看成在当前表中设置一个外键dept_no-->
        <many-to-one name="dept" class="Dept" column="dept_no"></many-to-one>
    </class>

</hibernate-mapping>

在“一”的一方测试


package zhongfucheng.domain;

import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

/**
 * Created by ozc on 2017/5/6.
 */
public class App {
    public static void main(String[] args) {

        //创建对象
        Dept dept = new Dept();
        dept.setDeptName("开发部");

        Employee zs = new Employee();
        zs.setEmpName("张珊");
        zs.setSalary(1111);
        Employee ls = new Employee();
        ls.setEmpName("李四");
        ls.setSalary(2222);

        //添加关系
        dept.getSet().add(zs);
        dept.getSet().add(ls);

        //获取加载配置管理类
        Configuration configuration = new Configuration();

        //加载User的映射文件!
        configuration.configure().addClass(Dept.class).addClass(Employee.class);

        //创建Session工厂对象
        SessionFactory factory = configuration.buildSessionFactory();

        //得到Session对象
        Session session = factory.openSession();

        //使用Hibernate操作数据库,都要开启事务,得到事务对象
        Transaction transaction = session.getTransaction();

        //开启事务
        transaction.begin();


        session.save(dept);
        session.save(zs);
        session.save(ls);

        //提交事务
        transaction.commit();

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

Hibernate执行了5条SQL语句

这里写图片描述


在“多”的一方测试


package zhongfucheng.domain;

import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

/**
 * Created by ozc on 2017/5/6.
 */
public class App {
    public static void main(String[] args) {

        //创建对象
        Dept dept = new Dept();
        dept.setDeptName("开发部");

        Employee zs = new Employee();
        zs.setEmpName("张珊");
        zs.setSalary(1111);
        Employee ls = new Employee();
        ls.setEmpName("李四");
        ls.setSalary(2222);

        //维护关系
        zs.setDept(dept);
        ls.setDept(dept);



        //获取加载配置管理类
        Configuration configuration = new Configuration();

        //加载User的映射文件!
        configuration.configure().addClass(Dept.class).addClass(Employee.class);

        //创建Session工厂对象
        SessionFactory factory = configuration.buildSessionFactory();

        //得到Session对象
        Session session = factory.openSession();

        //使用Hibernate操作数据库,都要开启事务,得到事务对象
        Transaction transaction = session.getTransaction();

        //开启事务
        transaction.begin();


        session.save(dept);
        session.save(zs);
        session.save(ls);



        //提交事务
        transaction.commit();

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

Hibernate执行了3条SQL

这里写图片描述

一对多和多对一总结

在一对多与多对一的关联关系中,保存数据最好的通过多的一方来维护关系,这样可以减少update语句的生成,从而提高hibernate的执行效率!

  • 配置一对多与多对一, 这种叫“双向关联”
  • 只配置一对多, 叫“单项一对多”
  • 只配置多对一, 叫“单项多对一”

值得注意是:配置了哪一方,哪一方才有维护关联关系的权限!

  • 当我在部门中不配置员工的关联关系了,那么在操作部门的时候就不能得到员工的数据了【也就是:在保存部门时,不能同时保存员工的数据】

<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
Hibernate一对多与多对一映射操作详解 对象关系映射(Object-Relational Mapping, ORM)是一种技术方法,使得程序人员能够将对象模型直接映射到关系数据库中。Hibernate是Java中广泛应用的ORM框架之一,它提供了透明化的持久层解决方案,使得开发者能够以面向对象的方式操作数据库,而无需直接处理SQL语句。在Hibernate中配置和操作实体类的集合属性涉及对特定注解的合理使用,并且要理解集合属性与数据库表之间的映射关系。 阅读详情

相关推荐

xenomai内核解析--嵌入式实时linux概述

Linux系统作为一个GPOS(通用操作系统)发展至今已经非常成熟可靠了,并且由于遵循GPL协议,开放所有系统源代码,非常易于裁剪。更重要的是,与其他开源的GPOS或RTOS相比,Linux系统支持多种处理器、开发板,提供多种软件开发工具,同时Linux系统对网络和图形界面的支持非常出色。显然,选择Linux操作系统在产品的开发周期和成本控制方面都有巨大优势。 虽然Linux系统功能强大、实用性强...

wsg1100 3702

Mybatis笔记05---一对多和多对一处理

10、多对一处理 多对一: 多个学生,对应一个老师 对于学生这边而言, 关联 … 多个学生,关联一个老师 【多对一】 对于老师而言, 集合 , 一个老师,有很多学生 【一对多】 SQL: CREATE TABLE `teacher` ( `id` INT(10) NOT NULL, `name` VARCHAR(30) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=INNODB DEFAULT CHARSET=utf8 INSERT INTO

weixin_42503072的博客 163

opencv基础57-模板匹配cv2.matchTemplate()->(目标检测、图像识别、特征提取)

OpenCV 提供了模板匹配(Template Matching)的功能,它允许你在图像中寻找特定模板(小图像)在目标图像中的匹配位置。模板匹配在计算机视觉中用于目标检测、图像识别、特征提取等领域。: 首先,加载目标图像和要匹配的模板图像。: 选择适当的匹配方法,例如 cv2.TM_CCOEFF、cv2.TM_CCOEFF_NORMED、cv2.TM_CCORR、cv2.TM_CCORR_NORMED、cv2.TM_SQDIFF 或 cv2.TM_SQDIFF_NORMED。每种方法对应不同的匹配计算方式。

小海聊智造 1万+

利用map集合实现一对多关系的映射

需求: (1)一对多关系的创建。 一个学校有多个教室,一个教室有多个学生。 假设一个学校有俩教室,每个教室有俩学生。 学校:xuexiao 教室:jiaoshi01、jiaoshi02 学生(甲乙丙丁+学号): jiaoshi01: jia A01、 yi A15 jiaoshi02: bing B01、 ding B05 分析: 无论如何,我们先将其存入Map容器。看下面...

qq_41858755的博客 1717

安卓ai自动化脚本 Yyds.Auto实现 示例 纯ai图像识别自动点击脚本

纯ai识别实现自动化脚本

专注安卓前沿科技 4785

phpstudy自定义安装mysql8.3并启动

下载压缩包文件然后按下面的图片一步一步操作选择版本,选择第一个压缩包文件,下载下载完成后,解压到phpstudy环境目录下

互联网碎碎念 2803

Mybatis入门学习十一:多对一与一对多的处理

多对一与一对多 多对一与多对一 这种东西举几个例子就明白了,就是数学里面的集合。 多个学生对一个老师,对学生这边而言,多个学生关联一个老师,对于老师而言,一个老师教很多学生。 多首歌曲对一个专辑。 在数据库中就是主键外键的关系,在java代码中,就是声明别的实体类作为当前实体类的一个属性的关系 多人运动? 废话不多说,淦就完了: 准备数据库 准备工作,在Mybatis(自己重新建一个也可以,到时候修改一些Mybatis的配置文件就行)数据库中,建立如下两个表,建立步骤不要一次性执行,由黄色分割线一步一步

weixin_41549354的博客 182

有道龙虾LobsterAI vs. OpenClaw:对比与安装部署攻略

LobsterAI是"中国版OpenClaw",更注重易用性和中文场景适配;OpenClaw是技术极客的玩具,需要大量命令行操作。

lpfasd123的博客 2400

给Hibernate多对多(一对多)集合属性的条件

public class ZgtcAirportIndexColunm extends BaseEntity implements java.io.Serializable { private Set roles = new HashSet(0); public Set getRoles() { return roles; } public void setRoles(Set...

李义星 495

作为一名爬虫人如何实现千万级数据爬取?

爬虫门槛不高,高就高在往后余生的每一次实操都随时会让你崩溃!Bro

吴秋霖的博客 1万+

LeRobot 机器人学习(Robot Learning)教程(二)经典机器人学

本文探讨了机器人学中基于学习的方法与传统动力学方法的对比与发展趋势。文章指出,传统方法依赖精确的动力学模型和大量人工调参,面临跨任务泛化能力弱、工程复杂度高、物理建模局限性等问题。随着机器学习技术的进步和机器人数据集的丰富,基于学习的方法展现出三大优势:(1)能够实现跨任务与实体的泛化;(2)降低对人类专业知识的依赖;(3)利用历史数据优化性能。文中以平面机械臂为例,分析了传统逆运动学方法的计算复杂性和环境适应性挑战,并指出基于学习的方案在处理高维感知输入、复杂接触动力学等方面具有明显优势。文章认为,结合物

2506_90492529的博客 1066

“有联系”如何建立联系和集合多对一

一、F - 小沙的算术 知识点:复杂度分析;并查集应用;并查集思想(数组实现,建立联系);可以开一些无用空间不填东西或者初始化成一个值;逆元、模计算;从后往前看问题(延时一步);从前往后看问题 首先分析这个问题的复杂度,把问题取个极限。比如这个题,如果全是乘法,按照我最朴素的模拟想法,即从乘法开始用指针找到加号为止,时间为1e6,不可取;如果全是一个乘法一个加法,则最多有1e6/2组,如果是用记录左和右坐标的方法还是不行。 这个问题的关键是 划分组别 int f[maxn] long lon

IsayIwant的博客 8554

基于深度学习的柑橘病害检测系统——YOLOv8 + UI界面 + 数据集

深度学习是机器学习的一种重要分支,它通过构建多层的神经网络(尤其是卷积神经网络CNN)来从大规模的数据中学习特征。近年来,深度学习特别是在计算机视觉领域取得了显著的进展,成为图像分类、目标检测、图像分割等任务的主要技术。对于农业病害检测问题,深度学习通过对大量带标签的病害图像进行训练,能够自动识别不同类型的病害,并判断病害的程度。通过图像中目标(病害区域)的边界框,可以快速定位病害区域,进一步分析其影响范围。

YOLO 1044

Hibernate关联映射之一对多,多对一以及双向一对多

在上篇博客我们讲了hibernate对单表的操作,本篇博客就来讲讲对多表的关联映射操作。首先我们拿来做例子的表为班级表1---n学生表,在这次的测试主键我用的是序列,创建代码如下: --班级表 drop table classes; create table classes( cid int primary key, cname varchar2(50) ); dr

韶shls的博客 5978

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Hibernate一对多/多对一关系映射详解及相应的增删查改操作

以客户与订单的关系为例 1.在实体模型类中绑定两者关系: 客户类: public class Customer { private Integer id;//客户id private String name;//客户名称 //一对多属性描述,一个客户有n个订单 private Set<Order> orders = new HashSet<Ord...

MoLi blog 1万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Hibernate框架【四】——基本映射——多对一和一对多映射

由于公司项目上进行面向对象的架构设计对于ORM部分使用的是Spring Data JPA框架。将ORM完全交给Spring Data JPA框架,而Hibernate是Spring Data JPA的实现方式之一,通过对HIbernate框架的学习能够更好的理解ORM框架,以及Spring Data JPA框架。下面的博客是对于Hibernate框架中的基本映射中的多对一和一对多映射进行的实践,总结的并不全面,旨在多对一和一对多映射关系有一个宏观了解并能够进行基本运用。

理想主义的花最终会盛开在浪漫主义的土壤里,我的热情永远不会熄灭在现实的平凡之中,我们终将上岸,阳光万里。 1461

hibernate中多对一、一对一、一对多、多对多的配置方法

hihernate一对多关联映射(单向Classes----->Student) 一对多关联映射利用了多对一关联映射原理 多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一 一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多 也就是说一对多和多对一的映射策略是一样的,只是站的角度不同 在一一端维护关系的缺点:  * 如果将t_studen

计算机技术学习与应用 9183

hibernate 单向多对一,一对多,双向多对一详解

1、单向多对一和双向多对一的区别? 只需要从一方获取另一方的数据时 就使用单向关联双方都需要获取对方数据时 就使用双向关系部门--人员使用人员时如果只需要获取对应部门信息(user.getdeptarment())不需要 从部门下的人员信息时,就配置成单向 多对一使用部门时如果只需要获取部门下人员信息(deptartmanet.getusers())不需要 从人员获取部门信息时,就配置成单向 一...

wanderlustLee的博客 1696

关系映射一对多,多对一详解

关系映射一对多,多对一 1,  一对多,如:部门表与用户表,一个部门是不是有多个用户,但是一个用户有且只有一个部门,很清晰了吧 2,  现在先写方部门类:Department.java     public class Deparment {     private int id;     private String name;     private Set emps;

张晓丛的专栏 3519

Hibernate-一对多和多对一

一对多和多对一的实例有很多,下面我们以员工和部门为例子: 首先创建主配置文件,设置jdbc的配置和连接池 <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hi

Evan_QB的博客 1059

hibernate多对一关联和一对多关联

1. 多对一的单向关联 从订单(order)到客户(customer)的单向关联 (多个订单对应一个客户) JavaBean: Customer public class Customer{ private Integer id; private String name; } JavaBean: Order public class Customer{ private Integ

技术人生 2808

Hibernate注解配置一对多双向关联和多对一单向关联

Hibernate提供了Hibernate Annotations扩展包,使用注解完成映射。在Hibernate3.3之前,需单独下载注解开发包   配置持久化类 配置关联关系  下面我们先从多对一单向关联关系讲起,多对一单向关联就是在多的一方植入一的一方的主键作为外键,下面我们先进行初始配置,   在配置的过程中我们会遇到一个问题  就是无论用load还是get都不会出现延迟...

龚道松 2167
上一篇: Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved tran
下一篇: Hibernate第五篇【inverse、cascade属性详解】
Java3y
Java3y 领域专家: 后端开发技术领域 领域专家: 后端开发技术领域
博客等级 码龄9年 1万+粉丝 509原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值