三大框架 之 Hibernate查询(一对多、多对多、查询关系)

目录

  • 一对多

    • 表之间关系
    • 表之间关系建表原则
    • 一对多关系配置
      • 建立表
      • 建立ORM
      • 添加配置文件
      • 添加核心配置文件
      • 引入工具类
      • 编写测试类
    • 级联操作
      • 什么是级联
      • 级联分类
      • 级联是有方向性
      • 级联保存或更新
      • 级联删除
      • 在双向级联的过程当中,会产生一些多余的sql语句
    • lazy懒加载(默认值是proxy,不自动获取外键对象)
    • 级联保存或更新(解决 瞬时对象异常,只保存一边)
  • 多对多
    • 多对多关系配置

      • 建立表
      • 建立ORM
      • 添加配置文件
      • 在核心配置文件当中添加两个新配置
      • 编写测试类
    • 多对多的操作
  • 查询方式
    • OID查询
    • 对象导航查询
    • HQL
      • 什么是HQL
      • 查询

一对多

表之间关系

? 一对多

  • 一个部门有多个员工,一个员工只能属于某一个部门
  • 一个班级有多个学生,一个学生只能属于一个班级

? 多对多

  • 一个老师教多个学生,一个学生可以被多个老师教
  • 一个学生可以先择多门课程,一门课程可以被多个学生选择
  • 一个用户可以选择多个角色,一个角色也可以被多个用户选择

? 一对一

  • 一个公司只能对应一个注册地址

表之间关系建表原则

? 一对多
? 在多的一方创建一个外键,指向一的一方的主键
? 多对多
? 创建一个中间表,中间表至少有两个字段,分别作为外键指向多对多双方的主键
? 一对一
? 唯一外键对应
? 主键对应

一对多关系配置

建立表

创建表的 hbm.xml文件时,有外键可不创建列的映射

主表为客户(Customer),从表为联系人(Linkman)

销售联系人(linkman),一个联系人只能属于某一个客户
?

CREATE TABLE `linkman` (
  `link_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)',
  `link_name` varchar(16) DEFAULT NULL COMMENT '联系人姓名',
  `link_cust_id` bigint(32) NOT NULL COMMENT '客户id',
  `link_gender` char(1) DEFAULT NULL COMMENT '联系人性别',
  `link_phone` varchar(16) DEFAULT NULL COMMENT '联系人办公电话',
  `link_mobile` varchar(16) DEFAULT NULL COMMENT '联系人手机',
  `link_email` varchar(64) DEFAULT NULL COMMENT '联系人邮箱',
  `link_qq` varchar(16) DEFAULT NULL COMMENT '联系人qq',
  `link_position` varchar(16) DEFAULT NULL COMMENT '联系人职位',
  `link_memo` varchar(512) DEFAULT NULL COMMENT '联系人备注',
  PRIMARY KEY (`link_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

客户(customer),一个客户可以有多个联系人
?

CREATE TABLE `customer` (
  `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)',
  `cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)',
  `cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源',
  `cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业',
  `cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别',
  `cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话',
  `cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话',
  PRIMARY KEY (`cust_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

关系图

建立ORM

1.实体类与数据库中字段进行建立

客户实体类

private Long cust_id;
private String cust_name;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_phone;
private String cust_mobile;

销售实体类
?

private Long   link_id;
private String link_name;
private String link_gender;
private String link_phone;
private String link_mobile;
private String link_email;
private String link_qq;
private String link_position;
private String link_memo;
private String link_cust_id;

2.设置两表之间的关系

一个客户可以有多个联系人

Customer类
package com.myxq.domain;
import lombok.Getter;
import lombok.Setter;
import java.util.HashSet;
import java.util.Set;
@[email protected]
public class Customer {
    private Long cust_id;
    private String cust_name;
    private String cust_source;
    private String cust_industry;
    private String cust_level;
    private String cust_phone;
    private String cust_mobile;
    //一个客户可以有多个联系人
    private Set<Linkman> linkmens = new HashSet<>();
    @Override
    public String toString() {
        return "Customer{" +
                "cust_id=" + cust_id +
                ", cust_name='" + cust_name + '\'' +
                ", cust_source='" + cust_source + '\'' +
                ", cust_industry='" + cust_industry + '\'' +
                ", cust_level='" + cust_level + '\'' +
                ", cust_phone='" + cust_phone + '\'' +
                ", cust_mobile='" + cust_mobile + '\'' +
                '}';
    }
}

一个联系人只能属于某一个客户

Linkman类
package com.myxq.domain;
import lombok.Getter;
import lombok.Setter;
@[email protected]
public class Linkman {
    private Long   link_id;
    private String link_name;
    private String link_gender;
    private String link_phone;
    private String link_mobile;
    private String link_email;
    private String link_qq;
    private String link_position;
    private String link_memo;
    private String link_cust_id;
    //一个联系人只对应一个客户
    private Customer customer;
    @Override
    public String toString() {
        return "Linkman{" +
                "link_id=" + link_id +
                ", link_name='" + link_name + '\'' +
                ", link_gender='" + link_gender + '\'' +
                ", link_phone='" + link_phone + '\'' +
                ", link_mobile='" + link_mobile + '\'' +
                ", link_email='" + link_email + '\'' +
                ", link_qq='" + link_qq + '\'' +
                ", link_position='" + link_position + '\'' +
                ", link_memo='" + link_memo + '\'' +
                ", link_cust_id='" + link_cust_id + '\'' +
                ", customer=" + customer +
                '}';
    }
}

?

添加配置文件

1.客户(Customer)实体类的配置文件

customer.hbm.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!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.myxq.domain.Customer" table="customer" >
        <!--建立类属性哪一个是主键  还要跟数据库当中主键进行对象-->
        <id name="cust_id" column="cust_id" >
            <generator class="native"/>
        </id>
        <!--建立类中的普通属性与数据库当中字段进行关联-->
        <property name="cust_name" column="cust_name" />
        <property name="cust_source" column="cust_source"/>
        <property name="cust_industry" column="cust_industry"/>
        <property name="cust_level" column="cust_level"/>
        <property name="cust_phone" column="cust_phone"/>
        <property name="cust_mobile" column="cust_mobile"/>
        <!--一对多-->
        <set name="linkmens" cascade="save-update,delete" inverse="true"><!--set属性名称-->
            <key column="link_cust_id"></key><!--外键-->
            <one-to-many class="com.myxq.domain.Linkman"></one-to-many>
        </set>

    </class>
</hibernate-mapping>

2.联系人(LinkMan)实体类配置文件

linkman.hbm.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!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.myxq.domain.Linkman" table="linkman" >
        <!--建立类属性哪一个是主键  还要跟数据库当中主键进行对象-->
        <id name="link_id" column="link_id" >
            <generator class="native"/>
        </id>
        <!--建立类中的普通属性与数据库当中字段进行关联-->
        <property name="link_name" column="link_name" />
        <property name="link_gender" column="link_gender"/>
        <property name="link_phone" column="link_phone"/>
        <property name="link_mobile" column="link_mobile"/>
        <property name="link_email" column="link_email"/>
        <property name="link_qq" column=" link_qq"/>
        <property name="link_position" column=" link_position"/>
        <property name="link_memo" column=" link_memo"/>
        <many-to-one name="customer" cascade="save-update" class="com.myxq.domain.Customer"
                     column="link_cust_id"/>
    </class>
</hibernate-mapping>

添加核心配置文件

引入工具类

编写测试类

级联操作

问题
? 在两张表建立一对多关系时,如果只保存一边的对象,就会发异常
示例

什么是级联

? 在操作一个对象的时候,是否会操作其关联的对象。

级联分类

? 级联保存或更新
? 级联删除

级联是有方向性

? 在操作一的一方,是否会操作多的一方
? 操作多的一方时, 是否会操作一的一方

级联保存或更新

级联保存

? 操作的主体是谁,就要在谁的映射配置文件当中进行配置
? 在开始配置的set当中添加一个新的属性cascade="save-update"

? 在多的一方添加级联

? 再去运行,就不会报异常,两条记录都会被添加
? 在一的一方添加级联
?

对象导航

? 两方如果都加了级联,这种我们也称为双向导航
? 设置双向导航时,当对象存在关系时, 就会做出对应的操作
?

级联更新

级联删除

删除一边数据时,同时将另一边的数据一并删除

不设置级联删除

? 默认:先把外键改为空,然后再删除

? 发送的SQL语句

设置级联删除

示例代码

配置文件

在双向级联的过程当中,会产生一些多余的sql语句

原因
? 当双向维护时,两都都维护了外键,当做更新操作时, 两边的外键都要去修改

解决办法

1.使用单向维护
? 有些地方还是会有问题
2.一方放弃维护权
? 在一的一方放弃外键维护权
? 在配置文件当中添加一个inverse="false/true"
? true为放弃外键维护权,false为不放弃外键维护权

cascade与inverse

? cascade控制有没有关联对象
? inverse控制有没有外键
? 示例

lazy懒加载(默认值是proxy,不自动获取外键对象)

改成false,获取外键对象

在linkman.hbm.xml

<many-to-one name="customer" class="com.myxq.domain.Customer" column="link_cust_id"
lazy="false"/>

级联保存或更新(解决 瞬时对象异常,只保存一边)

在customer.hbm.xml

<set name="linkmens" cascade="save-update,delete" inverse="true">
    <!--set属性名称-->
    <key column="link_cust_id"></key><!--外键-->
    <one-to-many class="com.myxq.domain.Linkman">
    </one-to-many>
</set>

多对多

多对多关系配置

建立表

用户表,一个用户可以有多个角色
?

CREATE TABLE `user` (
                  `user_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '用户id',
                  `user_code` varchar(32) NOT NULL COMMENT '用户账号',
                  `user_name` varchar(64) NOT NULL COMMENT '用户名称',
                  `user_password` varchar(32) NOT NULL COMMENT '用户密码',
                  `user_state` char(1) NOT NULL COMMENT '1:正常,0:暂停',
                  PRIMARY KEY (`user_id`)
                ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8;

角色表,一个角色可以被多个用户选择

CREATE TABLE `role` (
                  `role_id` bigint(32) NOT NULL AUTO_INCREMENT,
                  `role_name` varchar(32) NOT NULL COMMENT '角色名称',
                  `role_memo` varchar(128) DEFAULT NULL COMMENT '备注',
                  PRIMARY KEY (`role_id`)
                ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

关系图

建立ORM

  • 用户
  • 角色

?

import lombok.Getter;
import lombok.Setter;
import java.util.HashSet;
import java.util.Set;
@[email protected]
public class Role {
    private Long role_id;
    private String role_name;
    private String role_memo;
    //角色下面的所有用户
    private Set<User> users = new HashSet<>();
}

添加配置文件

用户

角色

在核心配置文件当中添加两个新配置

编写测试类

单向维护

双向维护

双向维护时,必须要有一方放弃外键维护
如果两边都有维护的话, 就会有重复的的记录,由于关系表是两个字段作为共同主键,不能有相同的记录
解决办法
? 通常都是让被动方放弃,用户选角色,角色为被动方

多对多的级联操作和一对多的级联操作是一样的

多对多的操作

关系的操作,只需要操作集合,就可以操作它们之间的关系
给用户添加一个新的角色

修改一个用户的角色

删除角色

查询方式

OID查询

什么是OID查询

  • 根据对象的OID主键进行检索

OID查询方式

  • get方法
  • load方法

对象导航查询

什么是对象导航检索

  • Hibernate根据一个已经查询到的对象,获得其关联的对象的一种查询方式
  • 先查询到联系人,就可以通过联系人获取联系人所关联的客户对象

有点像级联查询

HQL

什么是HQL

  • HQL查询:Hibernate Query Language,Hibernate的查询语言
  • 是一种面向对象的方式的查询语言,语法类似SQL。
  • 通过session.createQuery(),用于接收一个HQL进行查询方式。
  • 注意:使用时,不能用*,对于表,要采用别名查询

查询

简单查询

别名查询

排序查询

条件查询

? 位置绑定:根据参数的位置进行绑定条件

? 名称绑定:把参数对应的值起一个名称 再去设置名称

投影查询

? 查询对象的某个或某些属性
? 单个属性

? 多个属性

? 查询多个属性,封装到对象当中
? 要在类中,提供构造方法

分页查询

统#### 计查询
? 查询的结构只有一个

分组查询

多表查询

? 普通内连接

? 迫切内连接
?
? 通过hibernate将另一个对象的数据,封装该对象中

? 在普通内连接inner join 后添加一个关键字fetch

原文地址:https://www.cnblogs.com/mumuyinxin/p/10708180.html

时间: 2024-11-08 04:08:08

三大框架 之 Hibernate查询(一对多、多对多、查询关系)的相关文章

【SSH三大框架】Hibernate基础第十二篇:load()懒加载分析以及一对一、一对多、多对一、多对多懒加载的分析

一.懒加载的定义: 懒加载:在WEB应用程序中,经常会需要查询数据库,系统的响应速度在很大程度上是与数据库交互的响应.因此,如果能够优化与数据库的交互速度,则能够大大提高WEB应用的响应速度. 例如:当有一个Student类和一个Teacher类.当我们加载一个学生的所有信息,包括:学号,姓名等属性后,此时Student类中的Teacher类型的属性为null,当我们需要知道这个Student对应的Teacher属性的时候,我们才去加载这个Teacher对象. 如果,我们只需要知道学生信息,我们

【SSH三大框架】Hibernate基础第七篇:一对多关联关系的操作

相对于上文的多对一关系,这里又说明下一对多的关联关系. 在上文中,我们描述了多对一的关系,在关系数据库中也是多对一的关系,并且还是一对多的关系.但是,仅仅如此是不够的,Hibernate是一种面向对象的结构,在Hibernate中仍然是多对一的关系,但是没有一对多,所以我们需要额外添加一对多的关系. 部门实体类:Department.java package cn.itcast.hibernate.domain; import java.util.Set; public class Depart

Hibernate实体映射文件多对多等关系简单应用技巧

第一步,写注释: <!--xx属性,本类与Yy(类)的多对一 --> <!--xx属性,本类与Yy(类)的一对多 --> <!--xx属性,本类与Yy(类)的多对多 --> <!--xx属性,本类与Yy(类)的一对一 --> 第二部,拷模版 <!--xx属性,本类与Yy(类)的多对一 --> <many-to-one name="" class="" column="">&l

【SSH三大框架】Hibernate基础第八篇:多对多关联关系的操作

在Hibernate中的多对多关联关系,一般是不会使用的,因为对于数据库查询的时候时间复杂度太高. 我们在这里做的是学生和老师,一个学生可以有多个老师,一个老师可以有多个学生. 我们首先建立一个学生实体类:Student.java package cn.itcast.hibernate.domain; import java.util.Set; public class Student { private int id; private String name; private Set<Teac

三大框架 之 Hibernate框架概述(概述、配置、核心API)

目录 Hibernate框架概述 什么是框架 hibernate简介(JavaEE技术三层架构所用到的技术) hibernate是什么框架 ORM hibernate好处 Hibernate基本使用 下载框架 Hibernate目录 使用 常见配置 映射配置 核心配置 核心API Configuration SessionFactory sessionFactory简介 配置连接池 查看日志 工具类 session session的api Hibernate框架概述 什么是框架 软件的一个半成品

Java_Web三大框架之Hibernate+HQL语言基础

12.1 HQL语言基础Hibernate查询语言为HQL(Hibernate Query Language),可以直接使用实体类名及属性.HQL语法类似于SQL,有SQL的关键词如select.from.order by.count().where等等.不同的是HQL是一种完全面向对象的语言,能够直接查询实体类及属性.12.1.1 HQL语法HQL语法类似于SQL,是一种select...from...的结构.其中,from后跟的是实体类名,而不是表名.select后面跟的可以是实体对象,也可

Java三大框架之——Hibernate中的三种数据持久状态和缓存机制

Hibernate中的三种状态   瞬时状态:刚创建的对象还没有被Session持久化.缓存中不存在这个对象的数据并且数据库中没有这个对象对应的数据为瞬时状态这个时候是没有OID. 持久状态:对象经过Session持久化操作,缓存中存在这个对象的数据为持久状态并且数据库中存在这个对象对应的数据为持久状态这个时候有OID. 游离状态:当Session关闭,缓存中不存在这个对象数据而数据库中有这个对象的数据并且有OID为游离状态. 注:OID为了在系统中能够找到所需对象,我们需要为每一个对象分配一个

22Mybatis_订单商品数据模型_多对多查询以及对多对多查询的总结

之前讲了一对一,一对多查询,这篇文章讲的是多对多. 先给出需求:查询用户及用户购买商品信息. 我们由之前的文章知道,这个需求是多对多的. 还是那个终止我们的mybatis所做的不管是之前的一对一还是一对多还是多对多,都只是为了把查询出来的结果(每个字段)做好映射. 好,我们现在sqlyong上把数据查出来,然后做映射. 给出几张表的内容: User表: orderdetail表: orders表: items表: 我们根据需求(查询用户及用户购买商品信息)把sql语句写出来: sql: SELE

【SSH三大框架】Hibernate基础第六篇:多对一关联关系的映射、分析及添加、查询

这里举例子用的是:部门与员工的关系. 一个部门可以对应多个员工,这就是很明显的多对一关联关系. 我们需要建立两个实体类:员工(Employee).部门(Department) 员工类:Employee.java(在这里边我们增加了一个Department类型的属性,用来做关联) package cn.itcast.hibernate.domain; public class Employee { private int id; private String name; private Depar