数据库中表之间的关系:

一对一、一对多、多对多

一对多的建表原则:在多的一方创建外键指向一的一方的主键;

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

一对一建表原则:唯一外键对应:假设一对一中的任意一方为多,在多的一方创建外键指向一的一方的主键,将外键设置为唯一

      主键对应:一方的主键作为另一方的主键;

在hibernate中采用java对象关系描述数据表之间的关系:

一对多的映射关系的实现案例:

客户实体类:在hibernate系列一中已经实现点击连接查看:https://www.cnblogs.com/wang-xuan/p/9195795.html

同时在客户实体类中添加属性:

//一个客户对应多个联系人
private Set<LinkMan> linkMans = new HashSet<LinkMan>();
public Set<LinkMan> getLinkMans() {
return linkMans;
}
public void setLinkMans(Set<LinkMan> linkMans) {
this.linkMans = linkMans;
}

实现联系人实体类LinkMan:

package com.itwx.hibernate.pojo;

public class LinkMan {

	private Long lkm_id;
private String lkm_name;
private String lkm_gender;
private String lkm_phone;
private String lkm_mobile;
private String lkm_email;
private String lkm_qq;
private String lkm_position;
private String lkm_memo; private Customer customer; public Long getLkm_id() {
return lkm_id;
} public void setLkm_id(Long lkm_id) {
this.lkm_id = lkm_id;
} public String getLkm_name() {
return lkm_name;
} public void setLkm_name(String lkm_name) {
this.lkm_name = lkm_name;
} public String getLkm_gender() {
return lkm_gender;
} public void setLkm_gender(String lkm_gender) {
this.lkm_gender = lkm_gender;
} public String getLkm_phone() {
return lkm_phone;
} public void setLkm_phone(String lkm_phone) {
this.lkm_phone = lkm_phone;
} public String getLkm_mobile() {
return lkm_mobile;
} public void setLkm_mobile(String lkm_mobile) {
this.lkm_mobile = lkm_mobile;
} public String getLkm_email() {
return lkm_email;
} public void setLkm_email(String lkm_email) {
this.lkm_email = lkm_email;
} public String getLkm_qq() {
return lkm_qq;
} public void setLkm_qq(String lkm_qq) {
this.lkm_qq = lkm_qq;
} public String getLkm_position() {
return lkm_position;
} public void setLkm_position(String lkm_position) {
this.lkm_position = lkm_position;
} public String getLkm_memo() {
return lkm_memo;
} public void setLkm_memo(String lkm_memo) {
this.lkm_memo = lkm_memo;
} public Customer getCustomer() {
return customer;
} public void setCustomer(Customer customer) {
this.customer = customer;
} }

配置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.itwx.hibernate.pojo.LinkMan" table="linkman">
<id name="lkm_id" column="lkm_id">
<generator class="native" />
</id>
<property name="lkm_name" column="lkm_name" />
<property name="lkm_gender" column="lkm_gender" />
<property name="lkm_phone" column="lkm_phone" />
<property name="lkm_mobile" column="lkm_mobile" />
<property name="lkm_email" column="lkm_email" />
<property name="lkm_qq" column="lkm_qq" />
<property name="lkm_position" column="lkm_position" />
<!-- 配置关联对象 -->
<!--
many-to-one:代表多对一:
name属性:在实体类中的属性:一的一方的对象的名称;
class属性:一的一方的类的全路径
column:表中的外键,在一的一方中配置的外键;
-->
<many-to-one name="customer" class="com.itwx.hibernate.pojo.Customer"
column="lkm_cust_id" />
</class>
</hibernate-mapping>

核心配置文件hibernate.cfg.xml

<!-- 配置加载映射文件:全路径-->
<mapping resource="com/itwx/hibernate/pojo/Customer.hbm.xml"/>
<mapping resource="com/itwx/hibernate/pojo/LinkMan.hbm.xml"/>

Customer.hbm.xml配置文件添加一对多的关系映射配置

<!-- 配置多一之间的映射关系 -->
<!--
set标签:name属性:在实体类中的属性,指多的一方的集合的属性名称
key标签:column:多的一方的外键的名称
one-to-many标签:class属性:多的一方的类的全路径
-->
<set name="linkMans">
<key column="lkm_cust_id" />
<one-to-many class="com.itwx.hibernate.pojo.LinkMan"/>
</set>

测试类中进行测试一对多的关系映射

@Test
public void test4() {
// 获取当前与线程绑定的session
Session session = HibernateUtils.getCurrentSession();
// 开启事务
Transaction transaction = session.beginTransaction();
// 创建关系对象
Customer customer = new Customer();// 此处可以使用带参构造方法
customer.setCust_name("张三");
customer.setCust_source("产品"); LinkMan linkMan1 = new LinkMan();
linkMan1.setLkm_name("周芷若");
linkMan1.setLkm_phone("1223445");
LinkMan linkMan2 = new LinkMan();
linkMan2.setLkm_name("张无忌");
linkMan2.setLkm_gender("男");
// 建立关系
/**
* 首先获取到set集合对象,然后才能进行添加元素; 所以先调用getXXX()方法获取对象,然后add
*/
// 客户关联联系人
customer.getLinkMans().add(linkMan1);
customer.getLinkMans().add(linkMan2);
// 联系人关联客户
linkMan1.setCustomer(customer);
linkMan2.setCustomer(customer);
// 执行操作
session.save(linkMan1);
session.save(linkMan2);
session.save(customer);
// 提交事务
transaction.commit();
          //执行结果
/**
* Hibernate: insert into linkman (lkm_name, lkm_gender, lkm_phone,
* lkm_mobile, lkm_email, lkm_qq, lkm_position, lkm_cust_id) values (?,
* ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into linkman (lkm_name,
* lkm_gender, lkm_phone, lkm_mobile, lkm_email, lkm_qq, lkm_position,
* lkm_cust_id) values (?, ?, ?, ?, ?, ?, ?, ?) Hibernate: insert into
* customer (cust_name, cust_source, cust_industry, cust_level,
* cust_phone, cust_mobile) values (?, ?, ?, ?, ?, ?) Hibernate: update
* linkman set lkm_name=?, lkm_gender=?, lkm_phone=?, lkm_mobile=?,
* lkm_email=?, lkm_qq=?, lkm_position=?, lkm_cust_id=? where lkm_id=?
* Hibernate: update linkman set lkm_name=?, lkm_gender=?, lkm_phone=?,
* lkm_mobile=?, lkm_email=?, lkm_qq=?, lkm_position=?, lkm_cust_id=?
* where lkm_id=? Hibernate: update linkman set lkm_cust_id=? where
* lkm_id=? Hibernate: update linkman set lkm_cust_id=? where lkm_id=?
*/
}

级联操作:

指在主控方执行保存、更新和删除操作时,其关联(被控方)也执行相同操作。在映射文件中通过对cascade属性的设置来控制是否对关联对象采用级联操作,级联操作对各种关联关系都是有效的;

级联具有方向性:在保存一的一方级联多的一方和在多的一方可以级联一的一方;

在映射文件中配置cascade=“save-update”;

级联删除和级联保存、更新:谁是主控方,则可以在映射文件中配置cascade=“delete、save-update”,也可以同时配置;

级联删除:在set标签中配置cascade=“delete”或者在mony-to-one中配置cascade属性;

<many-to-one name="customer" class="com.itwx.hibernate.pojo.Customer"
column="lkm_cust_id" cascade="save-update" />

或者

<set name="linkMans" cascade="delete,save-update" >
<key column="lkm_cust_id" />
<one-to-many class="com.itwx.hibernate.pojo.LinkMan"/>
</set>

防止SQL语句冗余:双向维护关系,持久态对象可以自动更新数据库,更新客户的时候会修改一次外键,更新联系人的时候会修改一次外键,所以会产生SQL语句冗余;

解决方案:一方放弃外键的维护,通常交给多的一方去维护,所以一的一方就需要放弃维护,即需要配置inverse=“true”;

<set name="linkMans" cascade="delete,save-update" inverse="true">
            <key column="lkm_cust_id" />
            <one-to-many class="com.itwx.hibernate.pojo.LinkMan"/>
        </set>

hibernate系列之四的更多相关文章

  1. Hibernate 系列 学习笔记 目录 (持续更新...)

    前言: 最近也在学习Hibernate,遇到的问题差不多都解决了,顺便把学习过程遇到的问题和查找的资料文档都整理了一下分享出来,也算是能帮助更多的朋友们了. 最开始使用的是经典的MyEclipse,后 ...

  2. Hibernate 系列 01 - 框架技术 (介绍Hibernate框架的发展由来)

    引导目录: Hibernate 系列教程 目录 本篇导航: 为什么学习框架技术 框架的概念 主流框架的介绍 1.为什么学习框架技术 如何制作一份看上去具有专业水准的PPT文档呢?一个简单的方法就是使用 ...

  3. Hibernate 系列 02 - Hibernate介绍及其环境搭建

    引导目录: Hibernate 系列教程 目录 昨晚喝多了,下午刚清醒,继续搞Hibernate.走起. 觉得还行的话,记得点赞哈,给我这个渣渣点学习的动力.有错误的话也请指出,省的我在错误上走了不归 ...

  4. Hibernate 系列 03 - 使用Hibernate完成持久化操作

    引导目录: Hibernate 系列教程 目录 康姆昂,北鼻,来此狗.动次打次,Hibernate继续走起. 目录: 使用Hibernate实现按主键查询 使用Hibernate实现数据库的增.删.改 ...

  5. Hibernate 系列 04 - Hibernate 配置相关的类

    引导目录: Hibernate 系列教程 目录 前言: 通过上一篇的增删改查小练习之后,咱们大概已经掌握了Hibernate的基本用法. 我们发现,在调用Hibernate API的过程中,虽然Hib ...

  6. Hibernate 系列 05 - Session 类

    引导目录: Hibernate 系列教程 目录 前言: Session是Hibernate运作的中心,对象的生命周期.事务的管理.数据库的存取都与Session息息相关. 就如同在编写JDBC时需要关 ...

  7. Hibernate 系列 06 - 对象在JVM中的生命周期

    引导目录: Hibernate 系列教程 目录 Java对象通过new命令进行创建,Java虚拟机(Java Virtual Machine,JVM)会为新的Java对象在内存中开辟一个新空间以存放次 ...

  8. Hibernate 系列 07 - Hibernate中Java对象的三种状态

    引导目录: Hibernate 系列教程 目录 1. Java对象的三种状态 当应用通过调用Hibernate API与框架发生交互时,需要从持久化的角度关注应用对象的生命周期. 持久化声明周期是Hi ...

  9. Hibernate 系列 08 - 对象识别机制

    目录导读: Hibernate 系列 学习笔记 目录 本篇目录: 为了区别不同的对象,有两种识别方法: 1. 内存地址识别(“==”号识别) 2. equals()和hashCode()识别 1. 以 ...

随机推荐

  1. 计算机为什么要区别C盘,D盘,E盘等?

      为什么要区分C盘,D盘,E盘,F盘? 1)各盘出现背景 在计算机刚诞生的年代,还没有硬盘,那时数据存储主要靠软盘.软盘驱动器按照顺序占据了A和B盘符的位置,后来随着硬盘的应用,就出现了C盘及以后的 ...

  2. URAL 1145—— Rope in the Labyrinth——————【求树的直径】

    Rope in the Labyrinth Time Limit:500MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64 ...

  3. 从零开始的全栈工程师——js篇2.20(事件对象 冒泡与捕获)

    一.复习 面向对象 1)单例模式 2)工厂模式 3)构造函数 ①类js天生自带的类 基类object function array number math boolean date regexp st ...

  4. CSS Grid 布局学习笔记

    CSS Grid 布局学习笔记 好久没有写博客了, MDN 上关于 Grid 布局的知识比较零散, 正好根据我这几个月的实践对 CSS Grid 布局做一个总结, 以备查阅. 1. 基础用法 Grid ...

  5. C++基础--sizeof和strlen的区别

    首先,来运行一段程序: #include "stdafx.h" #include <stdio.h> #include <string.h> int mai ...

  6. jquery 滑块导航菜单

    带滑块的导航菜单,鼠标悬浮时,滑块会移动至鼠标位置,离开时,滑块会回到原来的位置,点击菜单之后滑块会停留在被点击菜单位置,等待下一次的鼠标悬浮事件或者点击事件,效果图: 图片效果不行,直接上代码: & ...

  7. check_mk 分布式监控

    http://mathias-kettner.com/checkmk_wato_distributed.html peer(贵族) 管理多个slave 复制配置文件 /etc/check_mk/con ...

  8. 更改Anaconda中Jupyter的默认文件保存目录

    转载:https://blog.csdn.net/u014552678/article/details/62046638 总结:修改Anaconda中的Jupyter Notebook默认工作路径的三 ...

  9. JavaScript(一) 对象基础

    1.定义类或对象 1.1 混合的构造函数/原型方法 用构造函数定义对象的所有非函数属性,类似于Java的构造方法.用原型方法定义对象的函数属性(方法).这种方法是使用比较广泛的定义类或对象的方法. / ...

  10. Laravel Scheduling Package

    Laravel 是在 App\Console\Kernel 类中的 schedule 方法去定义所有的调度任务. iBrand 产品作为一个电商类产品,本身业务需求非常庞大和复杂,全部定义在 sche ...