1.1 一对多XML关系映射

1.1.1 客户配置文件:

<?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 package="com.itheima.domain">

<class name="Customer" table="cst_customer">

<id name="custId" column="cust_id">

<generator class="native"></generator>

</id>

<property name="custName" column="cust_name"></property>

<property name="custLevel" column="cust_level"></property>

<property name="custSource" column="cust_source"></property>

<property name="custIndustry" column="cust_industry"></property>

<property name="custAddress" column="cust_address"></property>

<property name="custPhone" column="cust_phone"></property>

<!-- 一对多关系映射

涉及的标签

set:用于映射set集合属性

属性:

  name:指定集合属性的名称

  table:在一对多的时候写不写都可以。

   它指定的是集合元素所对应的表

one-to-many:用于指定当前映射配置文件所对应的实体和集合元素所对应的实体是一对多关系。

属性:

   class:指定集合元素所对应的实体类名称。

key:用于映射外键字段的。

属性:

   column:指定从表中的外键字段名称

-->

<set name="linkmans" table="cst_linkman">

<key column="lkm_cust_id"></key>

<one-to-many class="LinkMan"/>

</set>

</class>

</hibernate-mapping>

1.1.2 联系人配置文件:

<?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 package="com.itheima.domain">

<class name="LinkMan" table="cst_linkman">

<id name="lkmId" column="lkm_id">

<generator class="native"></generator>

</id>

<property name="lkmName" column="lkm_name"></property>

<property name="lkmGender" column="lkm_gender"></property>

<property name="lkmPhone" column="lkm_phone"></property>

<property name="lkmMobile" column="lkm_mobile"></property>

<property name="lkmEmail" column="lkm_email"></property>

<property name="lkmPosition" column="lkm_position"></property>

<property name="lkmMemo" column="lkm_memo"></property>

<!-- 多对一关系映射

涉及的标签:

many-to-one:用于建立多对一的关系映射配置

属性:

  name:指定的实体类中属性的名称

  class:该属性所对应的实体类名称。如果在hibernate-mapping上没有导包,则需要写全限定类名

  column:指定从表中的外键字段名称

-->

<many-to-one name="customer" class="Customer" column="lkm_cust_id" /> </class>

</hibernate-mapping>

1.2 多对多关系映射

1.2.1 用户配置文件:

<?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 package="com.itheima.domain">

<class name="SysUser" table="sys_user">

<id name="userId" column="user_id">

<generator class="native"></generator>

</id>

<property name="userCode" column="user_code"></property>

<property name="userName" column="user_name"></property>

<property name="userPassword" column="user_password"></property>

<property name="userState" column="user_state"></property>

<!-- 多对多关系映射

涉及的标签:

set:用于映射集合属性

属性:

name:指定集合属性的名称

table:指定的是中间表的名称,在多对多的配置时,必须写。

key:指定外键字段

属性:

column:指定的是当前映射文件所对应的实体在中间表的外键字段名称

many-to-many:指定当前映射文件所对应的实体和集合元素所对应的实体是多对多的关系

属性:

class:指定集合元素所对应的实体类

column:指定的是集合元素所对应的实体在中间表的外键字段名称

-->

<set name="roles" table="user_role_rel">

<key column="user_id"></key>

<many-to-many class="SysRole" column="role_id"></many-to-many>

</set>

</class>

</hibernate-mapping>

1.2.2 角色配置文件:

<?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 package="com.itheima.domain">

<class name="SysRole" table="sys_role">

<id name="roleId" column="role_id">

一对多保存操作:

1.1.1 保存操作

保存原则:先保存主表,再保存从表。

/**

* 保存操作

* 需求:

* 保存一个客户和一个联系人

* 要求:

* 创建一个客户对象和一个联系人对象

*  建立客户和联系人之间关联关系(双向一对多的关联关系)

*  先保存客户,再保存联系人

* 问题:

* 在使用xml配置的情况下:

当我们建立了双向的关联关系之后,先保存主表,再保存从表时:

会产生2条insert和1条update.

* 而实际开发中我们只需要2条insert。

*

*/

@Test

public void test1(){

//创建客户和联系人对象

Customer c = new Customer();//瞬时态

c.setCustName("TBD云集中心");

c.setCustLevel("VIP客户");

c.setCustSource("网络");

c.setCustIndustry("商业办公");

c.setCustAddress("昌平区北七家镇");

c.setCustPhone("010-84389340");

LinkMan l = new LinkMan();//瞬时态

l.setLkmName("TBD联系人");

l.setLkmGender("male");

l.setLkmMobile("13811111111");

l.setLkmPhone("010-34785348");

l.setLkmEmail("98354834@qq.com");

l.setLkmPosition("老师");

l.setLkmMemo("还行吧");

//建立他们的双向一对多关联关系

//l.setCustomer(c);

c.getLinkmans().add(l);

Session s = HibernateUtil.getCurrentSession();

Transaction tx = s.beginTransaction();

//按照要求:先保存客户,再保存联系人(此时符合保存原则:先保存主表,再保存从表)

s.save(c);//如果在把客户对象转成持久态时,不考虑联系人的信息。就不会有联系人的快照产生

s.save(l);

tx.commit();//默认此时会执行快照机制,当发现一级缓存和快照不一致了,使用一级缓存更新数据库。

}

1.1.1.1 保存时遇到的问题

我们已经分析过了,因为双向维护了关系,而且持久态对象可以自动更新数据库,更新客户的时候会修改一次外键,更新联系人的时候同样也会修改一次外键。这样就会产生了多余的SQL,那么问题产生了,我们又该如何解决呢?

其实解决的办法很简单,只需要将一方放弃外键维护权即可。也就是说关系不是双方维护的,只需要交给某一方去维护就可以了。通常我们都是交给多的一方去维护的。为什么呢?因为多的一方才是维护关系的最好的地方,举个例子,一个老师对应多个学生,一个学生对应一个老师,这是典型的一对多。那么一个老师如果要记住所有学生的名字很难的,但如果让每个学生记住老师的名字应该不难。其实就是这个道理。

所以在一对多中,一的一方都会放弃外键的维护权(关系的维护)。这个时候如果想让一的一方放弃外键的维护权,只需要进行如下的配置即可。

inverse的默认值是false,代表不放弃外键维护权,配置值为true,代表放弃了外键的维护权。代码如下:

解决多一条update语句的问题:

<set name="linkmans" table="cst_linkman" inverse="true">

<key column="lkm_cust_id"></key>

<one-to-many class="LinkMan"/>

</set>

<generator class="native"></generator>

</id>

<property name="roleName" column="role_name"></property>

<property name="roleMemo" column="role_memo"></property>

<!-- 多对多关系映射 -->

<set name="users" table="user_role_rel">

<key column="role_id"></key>

<many-to-many class="SysUser" column="user_id"></many-to-many>

</set>

</class>

</hibernate-mapping>

1.1.1 修改操作

/**

* 更新操作

* 需求:

* 更新客户

* 要求:

* 创建一个新的联系人对象

*  查询id为1的客户

*  建立联系人和客户的双向一对多关联关系

*  更新客户

* 问题:

* 当更新一个持久态对象时,它关联了一个瞬时态的对象。执行更新

* 如果是注解配置:什么都不会做

* 如果是XML配置:会报错

* 解决办法:

* 配置级联保存更新

*/

@Test

public void test2(){

//创建联系人对象

LinkMan l = new LinkMan();//瞬时态

l.setLkmName("TBD联系人test");

l.setLkmGender("male");

l.setLkmMobile("13811111111");

l.setLkmPhone("010-34785348");

l.setLkmEmail("98354834@qq.com");

l.setLkmPosition("老师");

l.setLkmMemo("还行吧");

Session s = HibernateUtil.getCurrentSession();

Transaction tx = s.beginTransaction();

//查询id为1的客户

Customer c1 = s.get(Customer.class, 1L);

//建立双向关联关系

c1.getLinkmans().add(l);

//l.setCustomer(c1);

//更新客户

s.update(c1);

tx.commit();

}

1.1.1.1 修改中遇到的问题:

什么是级联操作:

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

级联操作的方向性:

级联是有方向性的,所谓的方向性指的是,在保存一的一方级联多的一方和在保存多的一方级联一的一方。

【保存客户级联联系人】

首先要确定我们要保存的主控方是那一方,我们要保存客户,所以客户是主控方,那么需要在客户的映射文件中进行如下的配置。

代码如下:

解决报错的问题,配置级联保存更新:

<set name="linkmans" table="cst_linkman" cascade="save-update" inverse="true">

<key column="lkm_cust_id"></key>

<one-to-many class="LinkMan"/>

</set>

面试题:hibernate第三天 一对多和多对多配置的更多相关文章

  1. 2.1、Hibernate多表操作--一对多、多对一、多对多。

    一.什么是一对一.一对多.多对一及多对多关系(以简单的学生和老师的关系为例来说): 1.一对一:学生具有学号和姓名(假定没有同名的学生)这两个属性,那么我知道了学生的学号也就能找到对应的学生姓名,如果 ...

  2. Hibernate之关联映射(一对多和多对一映射,多对多映射)

    ~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习以下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...

  3. Hibernate之关联关系映射(一对多和多对一映射,多对多映射)

    ~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习一下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...

  4. hibernate一对多和多对一配置

    public class Dept { private int deptId; private String deptName; // [一对多] 部门对应的多个员工 private Set<E ...

  5. EF 一对一、一对多、多对多配置语句小记

    数据库实体间的关系无非有这么几种:一对一.一对多.多对多,这些关系在EF框架中分别有不同的创建方式: 1.在"Database First"模式中,这些关系通过SQL语句的方式建立 ...

  6. mybatis 一对多,多对一配置

    一. 简介: 本实例使用顾客和订单的例子做说明: 一个顾客可以有多个订单, 一个订单只对应一个顾客 二. 例子: 1. 代码结构图: 2. 建表语句: CREATE DATABASE test; US ...

  7. Hibernate入门(三)—— 一对多、多对多关系

    一.一对多关系 1.概念 ​ 一对多关系是关系型数据库中两个表之间的一种关系.通常在数据库层级中,两表之间是有主外键关系的.在ORM中,如何通过对象描述表之间的关系,是ORM核心. 2.Hiberna ...

  8. Hibernate知识点小结(三)-->一对多与多对多配置

    一.多表关系与多表设计 1.多表关系        一对一:            表的设计原则(分表原则):                优化表的性能                基于语意化分表 ...

  9. hibernate第三天 一对多 , 多对多

    1.1. 阐述你对inverse的理解 答: 1.inverse的默认值是false,代表不放弃外键维护权,配置值为true,代表放弃了外键的维护权. 2.双方维护外键会多产生update语句,造成浪 ...

随机推荐

  1. 使用document.domain和iframe实现站内AJAX跨域

    站内AJAX跨域可以通过document.domain和iframe实现,比如www.css88.com.js.css88.com.css88.com这3个域名其实是3个不同的域,很多时候www.cs ...

  2. java学习笔记 --- 多线程(线程安全问题——同步代码块)

    1.导致出现安全问题的原因: A:是否是多线程环境 B:是否有共享数据 C:是否有多条语句操作共享数据 2.解决线程安全问题方法: 同步代码块: synchronized(对象){ 需要同步的代码; ...

  3. 网络编程基础--IO模型

    一 IO模型介绍: 背景 是 Linux环境下 的 network IO , Third Edition: The Sockets Networking ”,.2节“I/O Models ”,Stev ...

  4. 如何用visual studio2013编写简单C语言程序

    vc++6.0 作为经典版本,虽然已经几乎淘汰,但还是有很多的初学者在使用.但当他们使用vs2013时会发现界面和操作和vc++6.0有了极大的不同,不知该如何 操作.随着vs2013的普及,更多人使 ...

  5. IntelliJ IDEA 12创建Maven管理的Java Web项目(图解)

    转:http://blog.csdn.net/zht666/article/details/8673609/ 本文主要使用图解介绍了使用IntelliJIDEA 12创建Maven管理的JavaWeb ...

  6. celery 停止执行中 task

    目录 原因 解决过程 原因 因为最近项目需求中需要提供对异步执行任务终止的功能,所以在寻找停止celery task任务的方法.这种需求以前没有碰到过,所以,只能求助于百度和google,但是找遍了资 ...

  7. django的工作图

  8. SVM模型进行分类预测时的参数调整技巧

    一:如何判断调参范围是否合理 正常来说,当我们参数在合理范围时,模型在训练集和测试集的准确率都比较高:当模型在训练集上准确率比较高,而测试集上的准确率比较低时,模型处于过拟合状态:当模型训练集和测试集 ...

  9. 调整 WiFi 驱动设置让 WiFi 信号更稳定

    调整 WiFi 驱动设置让 WiFi 信号更稳定 修改 WiFi 驱动中 的设置,将 Power Saving Mode 的值改为 CAM.

  10. [转]深入详解javascript之delete操作符

    最近重新温习JS,对delete操作符一直处于一知半解的状态,偶然发现一篇文章,对此作了非常细致深入的解释,看完有茅塞顿开的感觉,不敢独享,大致翻译如下. 原文地址:http://perfection ...