简介

学习Java有一段时间了,一直在忙碌着学习,每天大量的新知识和新技术来不及消化,第二天又接着学习。有想法有时会想一下,大部分作为学习者角色完成这段时间的学习。反正最终不忘记自己的初心和学习的意义。好啦~不闲扯了,今天小Hi入门,主要学习持久化对象概述、映射对象标识符、和如何操纵持久化对象

Hibernate简介

1、Hibernate是处于开发中的持久层框架,他是一个ORM映射工具(Object/RelationMapping,对象-关系映射,就是通过将Java对象映射到数据库表,通过操作Java对象,就可以完成对数据表的操作)。是轻量级JavaEE应用的持久层解决方案。
	1.开源的持久层框架.
	2.ORM(Object/Relational Mapping)映射工具,建立面向对象的域模型和关系数据模型之间的映射.
	3.连接java应用和数据库的中间件.
	4.对JDBC进行封装,负责java对象的持久化.
	5.在分层结构中处于持久化层,封装对数据库的访问细节,使业务逻辑层更专注于实现业务逻辑
2、流行数据库框架
	JPA Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系(只有接口规范)
	Hibernate 最流行ORM框架,通过对象-关系映射配置,可以完全脱离底层SQL
	MyBatis  本是apache的一个开源项目 iBatis,支持普通 SQL查询,存储过程和高级映射的优秀持久层框架
	Apache DBUtils 、Spring JDBCTemplate
3. 为什么要用Hibernate
	1、Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。 
	2、Hibernate是一个基于jdbc的主流持久化框架,是一个优秀的orm实现,它很大程度的简化了dao层编码工作。 
	3、Hibernate使用java的反射机制,而不是字节码增强程序类实现透明性 
	4、Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵活性很出色。它支持很多关系型数据库,从一对一到多对多的各种复杂关系

JDBC和Hibernate区别

JDBC的缺点
	代码比较繁琐
	没有做到数据缓存
	不是面向对象的开发
	移植性比较差
	事务处理不是特别好
	因为jdbc是最底层的操作,所以效率比较高
hibernate的优点
	代码比较简单
	具有缓存:一级缓存、二级缓存、查询缓存   命中率的概念
	面向对象的开发
	移植性比较强
hibernate的缺点
	支持的分布式事务比较弱
	如果一张表的数据有千万级别,不适合用hibernate来做
	如果表之间的关系相当复杂,不适合用hibernate来做

Hibernate组成

1、持久化类(POJO)对应与数据库的一张表
2、映射文件:建立持久化类与数据库中的表的对应关系
3、配置文件:用来描述连接数据库的信息

Hibernate环境搭建

1. Hibernate并没有提供日志的实现可以下载slf4j 和 log4j 开发包,整合Hibernate的日志系统到log4j 
2. 开始准备jar包
	拷贝Hibernate发型包\hibernate3.jar(1个)
	拷贝Hibernate发型包\lib\required下的所有jar(6个)
	拷贝Hibernate发型包\lib\jpa下的jar(1个)
	拷贝Log4j的核心jar包(1个)
	拷贝slf4j发型包\slf4j-log4j12-*.jar(1个)
	数据库驱动jar(MySQL就1个)
	如果用到日志,拷贝Hibenate发型包\project\etc\log4j.properties到构建路径中
3. 建立配置文件hibernate.cfg.xml(参考Hibernate发型包\project\etc\hibernate.properties)
	hibernate的配置文件可以分为两个部分: 数据库的连接配置(用户名、密码、url、数据库驱动)2、其他配置(方言、验证数据库结构、映射文件)
4. 创建数据库表和实体
	持久化对象的要求:
	提供一个无参数 public访问控制符的构造器(默认就是)
	提供一个标识属性,映射数据表主键字段
	所有属性提供public访问控制符的 set  get 方法
	属性应尽量使用基本数据类型的包装类型
5. 在实体类所在的包中,创建Java对象与数据库的映射文件。文件名为"实体类名-hbm.xml"
	配置class/id/property
6. 配置dtd连不上网情况下约束(hibernate3.jar中rg.hibernate下两个文件hibernate-configuration-3.0.dtd/hibernate-mapping-3.0.dtd)
7. 编码测试
	hibernate的SessionFactory在初始化阶段只初始化一次即可,所有使用静态代码块进行封装,其中Configuration是用来加载hibernate的配置文件和映射文件的,加载后可以获取SessionFactory

 

Hibernate基本API类介绍

Configuration 类负责管理 Hibernate 的配置信息。包括如下内容:
	•Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(对应 hibernate.cfg.xml 文件)
	•持久化类与数据表的映射关系(*.hbm.xml 文件)
SessionFactory接口
	SessionFactory是生成Session的工厂,构造 SessionFactory 很消耗资源,一般情况下一个应用中只初始化一个 SessionFactory 对象,SessionFactory 对象一旦构造完毕,即被赋予特定的配置信息(SessionFactory 对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。同时,SessionFactory还负责维护Hibernate的二级缓存)
Session接口
	Session 是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心,所有持久化对象必须在 session 的管理下才可以进行持久化操作。Session 对象有一个一级缓存,显式执行 flush 之前,所有的持久层操作的数据都缓存在 session 对象处,相当于 JDBC 中的 Connection
Transaction接口
	所有持久层都应该在事务管理下进行,即使是只读操作
	常用方法:
		•commit():提交相关联的session实例
		•rollback():撤销事务操作
		•wasCommitted():检查事务是否提交

 

Hibernate运行流程

1、应用程序先调用Configuration类,该类读取Hibernate配置文件及映射文件中的信息
2、并用这些信息生成一个SessionFactory对象
3、然后从SessionFactory对象生成一个Session对象
4、并用Session对象生成Transaction对象
	A、可通过Session对象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法对PO进行加载、保存、更新、删除、等操作
	B、在查询的情况下,可通过Session对象生成一个Query对象,然后利用Query对象执行查询操作;如果没有异常,Transaction对象将提交这些操作到数据库中

Java 应用的持久化分层

Hibernate中间件:Hibernate不和特定的业务领域相关,能够把任意一个Java应用与数据库系统连接,可以理解为是一种中间件	Hibernate的持久化对象:目的就是与数据库同步,使用对象操作数据库。实体域对象在内存中创建后,不能永久存在。将实体域对象永久保存起来,就是持久化的过程。通常只有实体域对象需要持久化,过程域对象和事件域对象一般不需要持久化。广义持久化指增、删、改、查
ORM:(Object/Relation Mapping): 对象/关系映射

-----------------------------------------------------------------------
1. ORM:(Object/Relation Mapping): 对象/关系映射
ORM中间件的使用方法 	采用元数据来描述对象-关系映射细节,元数据通常采用xml格式,并存放在专门的对象-关系映射文件中。只要配置了持久化类与表的映射关系,orm中间件在运行时就能够参照映射文件的信息,把域对象持久化到数据库中
2:hibernate之所以操作javabean的过程即操作数据库的表,这hibernate底层会调用javabean持久化对象的set和get方法,对数据进行赋值和取值,并获取字段名称,组织sql语句,并执行sql语句,达到效果
3:hibernate要求javabean中要使用包装数据类型(Integer,Long,String等)

 

对象关系映射

#知识点1:访问Hibernate中持久化类,两种访问角度:
	保存(save): 会调用持久化类中的setter方法
	查看(get): 会调用持久化类中的getter方法
#知识点2: 基本数据类型和包装类型区别
	基本类型可直接运算、无法表达null、数字类型的默认值为0
	包装类默认值是null。当对于默认值有业务意义的时候需要使用包装类
	*基本数据类型和包装类型对应的hibernate映射类型相同
#知识点3: Hibernate访问持久化类属性的策略
	1.propertye 默认值:表明hibernate通过getXXX和
     setXXX来访问类属性。推荐使用。提高域模型透明性。
	2.field:hibernate通过java反射机制直接访问类属性。对于没有
	 javabean方法的属性可设置该访问策略。
	3. noop(了解):它映射Java持久化类中不存在的属性,即主要用于HQL(用query接口测试,使用hql语句)中,当数据库中有某列,而实体中不存在的情况
#知识点4: 在持久化类的方法中加入程序逻辑	 
	在Customer.hbm.xml文件中无需映射firstname和lastname属性,而是映射name属性。尽管类中并没有name属性,由于hibernate不是直接访问Name属性,而是调用get、set方法,在此方法中加入程序逻辑,因此建立了Firstname、Lastname和表之间的联系
#知识点5: 设置派生属性
	利用<property>元素的formula属性,用来设置一个sql表达式,hibernate将根据它来计算出派生属性的值
	<property name="totalPrice" formula="(select sum(o.price) from b_customer o)"></property>
#知识点6: 控制insert、update语句
	映射属性				作用
	<property>
	 insert属性			若为false,在insert语句中不包含该字段,该字段永远不能被插入。默认值true。
	<property>
	 update属性			若为false,update语句不包含该字段,该字段永远不能被更新。默认值为true。
	<class>
	mutable属性			若为false,等价于所有的<property>元素的update属性为false,整个实例不能被更新。默认为true。
	<class>
	dynamic-insert属性	若为true,等价于所有的<property>元素的insert为true,保存一个对象时,动态生成insert语句,语句中仅包含取值不为null的字段。默认false。
	<class>
	dynamic-update属性	若为true,等价于所有的<property>元素的update为true,更新一个对象时,动态生成update语句,语句中仅包含属性值发生变化的字段。默认false
#知识点7: 处理sql引用表示符			
	在SQL语法中,表示符是指用于为数据库表、视图、字段或索引等名字的字符串,常规表示符不包括空格,也不包含特殊字符,因此无需使用引用符号。如果数据库表名或列名包含特殊字符,可以使用引用表示符(tab上面一个键)
#知识点8:设置类的包名
	如果在一个映射文件中包含多个类,并且这些类位于同一个包中,可以设置<hibernate-mapping>元素的package属性,避免为每个类提供完整的类名
	
***映射关系注意事项
	1. 类中的属性不一定与表中的字段一一对应,全部映射
    2. 表中的字段不一定与类中的属性一一对应,全部映射
	3. 关联关系不一定配置成双向的,可以只配置一边,那是name属性必须要填写
	4. 一个类可以映射多个表,一个表可以映射多个类

映射对象标识符

1.Hibernate的唯一性标识
	(1)Java按地址区分同一个类的不同对象.
	(2)关系数据库用主键区分同一条记录.	(3)Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系。对象的OID和数据库的表的主键对应。为保证OID的唯一性,应该让Hibernate来为OID赋值
2. hibernate支持自然主键和代理主键
	(1)自然主键:具有业务含义的字段,如name
	(2)代理主键:不具有业务含义的字段,如id
3. Hibernate的一级缓存和快照
	(1)一级缓存:
	hibernate在内存地址中存在一个一级缓存,存在在一级缓存中的对象,就说明该对象具有了持久化的能力,如果对象具有持久化能力就能操作数据库。一级缓存中的数据使用oid用来区分对象,当查询数据库的时候,如果一级缓存中存在oid的数据,则不会产生select语句,Hibernate对查询数据库实现了性能优化,当Session关闭,一级缓存的数据就没有了。如何让缓存中的数据一直存在呢(即使Session关闭也存在),大家可以期待Hibernate的二级缓存。
	(2)快照
	Hibernate除了在内存中定义一级缓存之外,还存在一个快照区域(即对数据库数据的一份复制),在提交事务(清理缓存)的时候,会用缓存的数据和快照的数据进行比对,如果没有发生变化不执行update语句,如果发生了变化,则执行update语句
4. 掌握increment、identity、assigned (自然主键)、uuid、联合主键等主键策略
	increment: 增量为1
	Identity支持自动增长类型,不为引发线程安全问题,效率较高
	assiged为自然主键,开发人员测试可以指定主键
	uuid是生成字符串id
	联合主键,通过<composite-id name="customerID" class="cn.itcast.h_oid.e_composite.CustomerID">实现

 

操纵持久化对象

1. 理解Hibernate中Session对象
	当session的save()方法持久化一个对象时,该对象被载入缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中。当试图get()、 load()对象时,会判断缓存中是否存在该对象,有则返回,此时不查询数据库。没有再查询数据库
	Session中的方法总结:
	flush: 进行刷新缓存(此时缓存中的数据并不丢失)的操作,让缓存和数据库同步 执行一系列sql语句,但不提交事务,;
		commit:先调用flush() 方法,然后提交事务. 则意味着提交事务意味着对数据库操作永久保存下来。
		refresh:再次刷新,让session和数据库同步,执行查询,把数据库的最新信息显示出来,更新本地缓存的对象状态.
	clear:清空缓存,等价于list.removeAll();
	close:执行先执行commit方法提交事务,再关闭Session的缓存
2. 在hibernate中java对象的状态
	Hibernate 把对象分为 4 种状态: 
		持久化状态, get/load/update/save/saveOrUpdate/Query对象中方法
		临时状态, new对象
		游离状态, 通过持久化状态转换evict/clear/close也称为脱管
		删除状态. delelte
	Session 的特定方法能使对象从一个状态转换到另一个状态
3. 小知识点: unsaved-value
	判断持久化类中的id是否和映射文件中的id相等,如果相等,执行插入操作,否则不执行。unsaved-value=0(默认值)