目录

一对多

表之间关系

​ 一对多

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

​ 多对多

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

​ 一对一

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

表之间关系建表原则

​ 一对多

​ 在多的一方创建一个外键,指向一的一方的主键

​ 多对多

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

​ 一对一

​ 唯一外键对应

​ 主键对应

一对多关系配置

建立表

创建表的 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

实体类与数据库中建立字段关系

Customer 实体类(一个客户可以有多个联系人)
package com.myxq.domain;
import lombok.Getter;
import lombok.Setter;
import java.util.HashSet;
import java.util.Set;
@Getter@Setter
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;
//建立一个客户可以有多个联系人
//放置多的一方的集合,hibernate默认使用的是Set集合
//如果使用List的话,它要对List进行排列,在表中要多建这一列,用来排序
//一般使用的都是Set集合
//现在是双向关联,从客户能查联系人,从联系人也能查客户
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;
@Getter@Setter
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" >
<!--建立类属性哪一个是主键 还要跟数据库当中主键进行对象-->
<!-- 设置主键与OID的对应关系 -->
<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:一的一方对象属性名称
class:一的一方类的全路径
column:多的一方表的外键名称
-->
<many-to-one name="customer" cascade="save-update" class="com.myxq.domain.Customer" column="link_cust_id"/>
</class>
</hibernate-mapping>

在hibernate.cfg.xml中的标签里,添加核心配置文件

		<!--加载映射文件-->
<mapping resource="com/myxq/domain/customer.hbm.xml" />
<mapping resource="com/myxq/domain/linkman.hbm.xml" />
<mapping resource="com/myxq/domain/role.hbm.xml" />
<mapping resource="com/myxq/domain/user.hbm.xml" />

引入工具类

HibernateUtil.java

package com.myxq.utils;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; public class HibernateUtil {
public static final SessionFactory sessionFactory;
static {
//1.加载配置文件
Configuration configure = new Configuration().configure();
//configure.addResource("com/myxq/domain/Customer.hbm.xml");
//2.创建sessionFactory --JDBC 连接池
sessionFactory = configure.buildSessionFactory();
}
public static Session openSession(){
Session session = sessionFactory.openSession();
return session;
}
public static Session getCurrentSession(){
Session session = sessionFactory.getCurrentSession();
return session;
}
}

编写测试类

级联操作

问题

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

示例

什么是级联

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

级联分类

​ 级联保存或更新

​ 级联删除

级联是有方向性

​ 在操作一的一方,是否会操作多的一方

​ 操作多的一方时, 是否会操作一的一方

级联保存或更新

级联保存

​ 操作的主体是谁,就要在谁的映射配置文件当中进行配置

​ 在开始配置的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

  • 用户
  • 角色



Role.java

import lombok.Getter;
import lombok.Setter;
import java.util.HashSet;
import java.util.Set;
@Setter@Getter
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

QBC

什么是QBC

​ Query By Criteria,条件查询。是一种更加面向对象化的查询的方式。

查询

简单查询

排序查询

分页查询

条件查询

条件
= eq
> gt
> = ge
< lt
<= le
<> ne
like
in
and
or
单个条件

多个条件

统计查询

离线条件查询
  • 脱离Session,添加条件
  • 可以在外部提前使用DetachedCriteria对象提交设置好条件
  • 最后再绑定到session当中

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

  1. 2018.11.4 Hibernate中一对、多对多的关系

    简单总结一下 多表关系 一对多/多对一 O 对象 一的一方使用集合. 多的一方直接引用一的一方. R 关系型数据库 多的一方使用外键引用一的一方主键. M 映射文件 一: 多: 操作: 操作管理级别属 ...

  2. mybatis报错:查询一对多或多对多时只返回一条数据的问题

    问题: 使用映射文件实现查询一对多或多对多时只返回一条数据问题 解决方法: 导致这种情况出现的问题是因为两个表中的主键是一样所以出现了数据覆盖问题. 解决方式一:修改数据库表中的主键(这种方法比较麻烦 ...

  3. java框架之Hibernate(3)-一对多和多对多关系操作

    一对多 例:一个班级可以有多个学生,而一个学生只能属于一个班级. 模型 package com.zze.bean; import java.util.HashSet; import java.util ...

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

    目录 Hibernate框架概述 什么是框架 hibernate简介(JavaEE技术三层架构所用到的技术) hibernate是什么框架 ORM hibernate好处 Hibernate基本使用 ...

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

    12.1 HQL语言基础Hibernate查询语言为HQL(Hibernate Query Language),可以直接使用实体类名及属性.HQL语法类似于SQL,有SQL的关键词如select.fr ...

  6. java三大框架——Struts + Hibernate + Spring

    Struts主要负责表示层的显示 Spring利用它的IOC和AOP来处理控制业务(负责对数据库的操作) Hibernate主要是数据持久化到数据库 再用jsp的servlet做网页开发的时候有个 w ...

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

    Hibernate中的三种状态   瞬时状态:刚创建的对象还没有被Session持久化.缓存中不存在这个对象的数据并且数据库中没有这个对象对应的数据为瞬时状态这个时候是没有OID. 持久状态:对象经过 ...

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

    之前讲了一对一,一对多查询,这篇文章讲的是多对多. 先给出需求:查询用户及用户购买商品信息. 我们由之前的文章知道,这个需求是多对多的. 还是那个终止我们的mybatis所做的不管是之前的一对一还是一 ...

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

    这里举样例用的是:部门与员工的关系. 一个部门能够相应多个员工,这就是非常明显的多对一关联关系. 我们须要建立两个实体类:员工(Employee).部门(Department) 员工类:Employe ...

随机推荐

  1. SIM800A 建立网络

    SIM800A是一款两频GSM/GPRS模块,为SMT封装.其性能稳定,外观小巧,性价比高 可以低功耗实现语音.SMS和数据信息的传输 数据传输 GPRS class 12:最大85.6 kbps(下 ...

  2. laravel使用withCount获取列表下关联模型的数量

    模型里面 <?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Post extends Model ...

  3. 使用jib上传docker镜像

    Jib 无需Docker守护程序即可为Java应用程序构建优化的Docker和OCI映像-无需深入了解Docker最佳实践.它可以作为Maven和Gradle的插件以及Java库使用. 我使用的是Ma ...

  4. Kubernetes-使用Helm安装istio

    添加istio库: helm repo add istio.io https://storage.googleapis.com/istio-release/releases/1.3.4/charts/ ...

  5. Apache 安装后Error 403的故障排错方法(linux)

    Apache 安装后Error 403的故障排错方法 2018年01月07日 14:25:41 个人分类: Linux 一.问题描述 在apache2的httpd配置中,很多情况都会出现403. 刚安 ...

  6. 利用ssh的用户配置文件config管理ssh会话

    通常利用 ssh 连接远程服务器,一般都要输入以下类似命令: ssh user@hostname -p port 如果拥有多个 ssh 账号,特别是像我这种喜欢在终端里直接 ssh 登陆,不用 PuT ...

  7. (Linux基础学习)第二章:CentOS7.4安装教程

    001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 ...

  8. StringComparison 枚举

    地址:https://docs.microsoft.com/zh-cn/dotnet/api/system.stringcomparison?redirectedfrom=MSDN&view= ...

  9. linux网络编程之socket编程(一)

    今天开始,继续来学习linux编程,这次主要是研究下linux下的网络编程,而网络编程中最基本的需从socket编程开始,下面正式开始学习: 什么是socket: 在学习套接口之前,先要回顾一下Tcp ...

  10. Spring-05 -AOP [面向切面编程] -Schema-based 实现aop的步骤

    一.AOP [知识点详解] AOP:中文名称面向切面编程 英文名称:(Aspect Oriented Programming) 正常程序执行流程都是纵向执行流程 3.1 又叫面向切面编程,在原有纵向执 ...