Hibernate关系部分(二)

简介

今天学习之前闲扯一下。比如现在学hibernate为什么要学这么多,其实学习这回事,最重要的掌握学习方法,要有想法,掌握解决问题的一种思路。但作为学习者一定要勤奋,大量的练习,解决很多错误,后期做项目也就少些bug了,有一句话不是说代码量都是长期积累下来的嘛。主要了解hibernate关系部分,包括一对多单项、一对多双向、多对多双向、一对一

一对多单项关系

一对多的关联关系
	Customer: 	id		name		Set<Order>
	Order:		id		orderNum
Order.hbm.xml
<many-to-one name="customer" class="cn.itcast.oneToMany.Customer" cascade="save-update">
	<column name="customer_id"></column>
</many-to-one>

多对一关联关系
	Cusomter:	id		name
	Order:		id		name		Customer
Customer.hbm.xml配置文件中
<set name="orders" cascade="save-update">

级联
	1. 在*.hbm.xml配置文件中配置<set name="students" cascade="save-update">
	2. 代码中,必须建立关联	classes.setStudents(students);
	3. 必须显示操作classes	session.save(classes)
		显示操作	seession.save(classes)
		隐式操作
			当保存classes的时候,同时保存了student,而保存student操作是由hibernate内部来完成的。并不是程序员显示操作的,所以称为隐式操作
隐式操作流程:
在执行session.flush的时候,
	 1、会检查hibernate一级缓存中所有的持久化状态的对象,来决定发出
		   insert语句或者update语句
	 2、会检查这些持久化对象中有没有关联对象,如果有,则再次去检查这些
		|--持久化状态的对象中有没有设置级联,如果有
			|--则检查关联对象是否是持久化状态的对象
				|--如果是,则再次检查副本
					|--如果不一样,则隐式发出update语句
				|--关联对象不是持久化状态的对象
					|--则发出insert语句
	3、检查持久化对象是否有维护关系的权利,就是检查持久化对象对应的映射文件中的inverse属性是否为false/default,如果是该值,则会自动维护关系(会发出维护关系的update语句)

一对多双向

一、 一对多双向关系
	1、一般情况下,一对多,多的一方维护关系,效率比较高
	2、如果一的一方维护关系,会单独发出维护关系的update语句
	3、在Customer.hbm.xml文件中
	<set name="orders" table="j_order" cascade="save-update" inverse="false" order-by="id desc">
		根据外键可以生成sql语句,因为设计到两张表,必须给定外键
		<key>
			<column name="cid"></column>
		</key>
		建立类与类之间的关系
		<one-to-many class="cn.itcast.oneToManyDouble.Order"/>
		指的是通过Customer建立Customer与Order之间的关系
	</set>
	4. 在Order.hbm.xml文件中
		<many-to-one name="customer" class="cn.itcast.k_oneToManyDouble.Customer" cascade="save-update">
					<column name="cid"></column>
		</many-to-one>
		指的是通过Order建立Customer与Order之间的关系
	5、在客户端的编码中,发出的sql语句越少,效率越高。
	6、如果是Order维护关系,不需要发出额外的更新关系的update语句,因为对学生的修改就直接包括了cid

二、 定义接口类型属性
	Hibernate要求在持久化类中定义集合属性时,必须把属性声明为接口类型,如Set、Map、List.声明为接口类型可提高持久化类的透明性,当hibernate调用setOrders()方法时,传递的参数是Hibernate自定义的实现该接口类的实例。如果定义成类(如HashSet)型,强迫hibernate把该类型的实例传给他。
        底层代码:
         Set<E> orders= PersistentSet
         class PersistentSet  implements java.util.Set
      通常在定义集合属性时,直接初始化为一个实现类的实例。
      private Set orders = new HashSet(0);
      可避免空指针异常
三、 set中inverse属性
	在hibernate中通过对 inverse 属性的值决定是由双向关联的哪一方来维护表和表之间的关系. inverse=false的为主动方,inverse=true 的为被动方, 由主动方负责维护关联关系
	结论:
		1.在映射一对多的双向关联关系时,应该在one方把inverse属性设为true,这可以提高性能。
		2.在建立两个对象的关联时,应该同时修改关联两端的相应属性:
		   customer.getOrders().add(order);
		   order.setCustomer(customer);
		这样才会使程序更加健壮,提高业务逻辑层的独立性,使业务逻辑层的程序代码不受Hibernate实现类的影响。同理,当删除双向关联的关系时,也应该修改关联两端的对象的相应属性:
		Customer.getOrders().remove(order);
		Order.setCustomer(null);

多对多双向

1. 多对多描述是类与集合的关系
	Course:	cid		name	Set<Student>
	Student:sid		name	Set<Course>
2. 映射文件中关联
# course通过student_course表的cid与student关联
	<set name="students" table="k_student_course" cascade="delete">
		<key>
			<column name="cid"></column>
		</key>
		<many-to-many class="cn.itcast.manyToMany.Student" column="sid"></many-to-many>
	</set>

# student通过student_course表的sid与course关联
	<set name="courses" table="student_course" inverse="true">
		<key>
			<column name="sid"></column>
		</key>
		<many-to-many class="cn.itcast.manyToMany.Course" column="cid"></many-to-many>
	</set>

总结:
	1、一对多指的是类与集合的关系
	2、多对一指的是类与类的关系
	3、多对多指的是类与集合的关系
	4、一对多的情况下,多的一方维护效率比较高
	5、一对多的情况下,维护关系指的是对外键进行update操作(一的一方维护关系)
		  多的一方维护关系,只是对多的一方进行所有的属性进行操作
	6、多对多维护关系
		  建立关系
			   在第三张表中插入一行数据
		  解除关系
			   在第三张表中删除一行数据
		  重新建立关系
			   先删除后增加
	7、因为多对多谁维护关系效率都一样,所以在映射文件中不需要写inverse属性
	8、一般情况下一对多,在一的一方inverse属性设置为"true"

检索策略

1. 延迟加载
	1). 当真正需要数据的时候,才要向数据库要数据,当加载属性的时候才发出sql语句,这种现象称为类的延迟加载
		代理实例有以下特征:
			代理类实例有如下特征:
			由 Hibernate 在运行时采用 javassist 工具动态生成
			Hibernate 创建代理类实例时, 仅初始化其 OID 属性
?在应用程序第一次访问代理类实例的非 OID 属性时, Hibernate 会初始化代理类实例
	2). session.load方法可以做类的延迟加载,产生出来的是一个代理对象,产生的代理类是 classes的子类
2. session.load方法和get方法的区别
	1、session.load方法用延迟加载,但是session.get方法不用延迟加载
	2、如果主键在数据库中没有对应的值,session.get方法返回的是null,但是不报错
		session.load方法,当得到属性的时候,会报错ObjectNotFountException
	3、session.load方法有可能会导致no session的异常,但是session.get方法不会
3, 在配置文件中配置延迟加载
	在Classes.hbm.xml文件中
	<class name="com.itheima10.hibernate.domain.Classes" lazy="false">
	如果lazy为false,则延迟加载失效
4. manytoone的延迟加载(单端关联)
	因为根据多的一方加载一的一方,加载一个数据,所以对效率影响不大,所以可以忽略
5. 抓取策略
	1). 策略为:先加载classes表中的数据,再根据每一个cid去student表中加载。所以
    如果含有子查询,这种策略会造成n+1条sql语句
	2). hibernate底层会生成子查询,所以如果需求分析中含有子查询的sql语句,用这种策略
    效率比较高
	3). 左外连接,一次性把classes和student的数据提取出来,但是如果含有子查询,
    则该策略失效
	***该策略是在映射文件中通过set元素中的fetch属性作用的,一旦映射文件确定了以后就不能修改了。所以抓取策略只不过是hibernate提供的一种优化策略而已
6. 提高性能总结
	1、一级缓存通过减少与数据库的交互次数提高效率
    2、二级缓存通过把一些常用的不变的对象放入到缓存中提高效率
    3、查询缓存通过把数据放入到查询缓存中提高效率
    4、延迟加载是通过改变sql语句发出的时间来提高效率的
    5、抓取策略是通过发生怎么样的sql语句提高效率的
	通过以上的5种方式可以尽量减少发出sql语句的数量,从而提高效率
时间: 2024-10-03 04:00:46

Hibernate关系部分(二)的相关文章

Hibernate 关系配置

表之间关系 1. 一对多 一个部门有多个员工,一个员工只能属于某一个部门 一个班级有多个学生,一个学生只能属于一个班级 2. 多对多 一个老师教多个学生,一个学生可以被多个老师教 一个学生可以先择多门课程,一门课程可以被多个学生选择 3. 一对一 一个公司只能对应一个注册地址 表之间关系建表原则 1. 一对多 在多的一方创建一个外键,指向一的一方的主键 2. 多对多 创建一个中间表,中间表至少有两个字段,分别作为外键指向多对多双方的主键 3. 一对一 唯一外键对应 主键对应 一对多关系配置 一.

Java学习笔记-Hibernate关系映射

1. 初识Hibernate——关系映射 http://blog.csdn.net/laner0515/article/details/12905711 2. Hibernate 笔记8 关系映射1(多对一,一对多): http://www.cnblogs.com/zilong882008/archive/2011/11/05/2236559.html 3. Hibernate关联映射 http://www.cnblogs.com/huxi/archive/2009/12/15/1624988.

hibernate 关系映射文件配置

<!--Department.hbm.xml users属性,本类与User的一对多 --> <set name="users"> <key column="departmentId"></key> <one-to-many class="User" /> </set> <!-- parent属性,本类与Department(上级)的多对一 --> <man

mysql关系(二维表)的设计规范,范式

范式,NF,normal format,就是指对表的结构的要求! 目的:1,规范结构!2,减少数据冗余! 第一范式,1NF,字段原子性 要求字段不能再分,要求字段的原子性 第二范式,2NF,非部分依赖 增加唯一主键即可!ID 范式的要求,是逐渐递增! 在满足 了 第一范式的前提下,不能出现部分依赖! 部分依赖指的是:普通字段对 主键 是完全依赖的,而不应该是依赖主键的一部分! 依赖:可以通过那个字段去决定另一个字段 因此,出现主键部分依赖的前提是,出现复合主键! 其中代课时间,开始和结束时间,没

浅谈Hibernate关系映射(3)

继上篇博客 一对多关联映射(单向) 上面我们介绍了多对一,我们反过来看一对多不就是多对一吗?那还用再进行不同的映射吗?有什么差别吗?一对多和多对一映射原理是一致的,存储是相同的,也就是生成的数据库的表是一样的,他们之间不同的是维护的关系不同. 他们之间不同点是维护的关系不同 *多对一维护的关系是:多指向一的关系,有了此关系,加载多的时候可以将一加载上来. *一对多维护的关系是:一指向多的关系,有了此关系,在加载一的时候可以将多加载上来. 一个班级有多个学生,通过班级可以看到学生信息. Class

浅谈Hibernate关系映射(2)

继上篇博客 一对一关系映射:一对一关联映射在实际生活中是比较常见的,如人与身份证的关系,通过人这个对象可以找到他相关的内容. 一对一单向(主键): 单向一对一主键关联,靠的是它们的主键相等,从Person中能看到IdCard,也就是把t_idCard中的主键拿过来当做t_Pseron的主键. 如图的线表示一个关联,在person中可以看见idcard.即在person中持有idCard的引用 person类的映射关系 <hibernate-mapping> <class name=&qu

浅谈Hibernate关系映射(4)

继上篇博客 多对多关联映射(单向) 多对多对象关系映射,需要加入一张新表完成基本映射. Hibernate会自动生成中间表 Hibernate使用many-to-many标签来表示多对多的关联,多对多的关联映射,在实体类中,跟一对多一样,也是用集合来表示的. 如下图所示 通过User可以查看Role的信息 User的映射文件 <hibernate-mapping> <class name="com.bjpowernode.hibernate.User"> <

Hibernate关系映射基础

1.  Hibernate关系映射基础 1.1.  Doctype <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 指定根元素和dtd文件的命名空间. 1.2.  hibernate-mapping <hiberna

hibernate关系映射(一对一)

一对一关联分为外键关联和主键关联:外键关联是指从表中存在主表的外键,这也是一种特殊的多对一关系:主键关联是指主从表的id一致 外键关联 主表:IDCard(校园卡) 从表:Student(学生) 学生类的定义和hbm文件的配置如下 1 public class Student { 2 private int id; 3 private String name; 4 //持有idcard的外键 5 private IDCard idCard; 6 }  可以看到 学生持有校园卡外键的类结构和之前多