================
目录
1.Hibernate框架作用和优点
2.Hibernate框架原理
3.Hibernate体系结构
4.Hibernate主要API
5.Hibernate基本使用步骤
6.Hibernate映射数据类型
7.Hibernate主键生成方式
8.Hibernate框架基本特性
9.OpenSessionInView模式
10.关联映射
11.一对多关系映射
12.多对一关系映射
13.关联操作
14.多对多关系映射
15.如何利用Myeclipse生成hbm.xml和实体类
16.继承关系映射
17.Hibernate查询
18.二级缓存
19.查询缓存
20.锁机制
备注:优先使用多对一,有需要再使用一对多
===============================
第一天
==================
1.Hibernate框架作用和优点
Hibernate用于访问数据库,对数据库进行增删改查操作。
利用Hibernate可以简化数据库操作代码。
原有JDBC技术访问数据库有以下问题:
a.需要拼写大量的SQL语句
b.需要编写大量的代码,完成实体对象和数据库表记录之间的相互转化
c.当数据库移植时,有些特殊的SQL语句需要改变。例如分页查询,数据库函数等。
Hibernate优点是解决了以上这些问题,并且引入了一些性能优化的机制。
2.Hibernate框架原理
Hibernate框架是对JDBC技术的一个封装。
Hibernate框架是基于ORM思想设计出来的。
ORM全称Object Relation Mapping 对象关系映射。
意思是可以完成Java实体对象与关系数据库中记录之间的映射工作。
利用ORM工具,查询时,可以直接以实体对象的形式获取数据库数据;
在添加、更新时,可以将对象更新到数据库表形式记录。
中间对象和记录的转换过程框架自动完成,对开发者是透明的。
Hibernate是ORM工具中非常流行的一款实现框架。此外还有一些其它的ORM工具,例如:
iBATIS,JPA,TOPLINK等
*3.Hibernate体系结构
1)Java实体类(n个)
主要用于封装数据库记录。
2)hibernate.cfg.xml(仅1个)
Hibernate框架主配置文件,用于定义数据库连接参数和框架的参数设置。
3)hbm.xml映射描述文件(n个)
Hibernate框架会根据hbm.xml文件的描述完成Java对象和数据表记录之间的映射
4)Hibernate API
在Java应用层采用Hibernate提供的API对那些映射过来的对象操作,
就可以完成对数据库的操作。
具体操作细节,Hibernate在底层进行了封装,可以不用关心。
*4.Hibernate主要API
1)Configuration
主要用于加载hibernate.cfg.xml配置文件
2)SessionFactory
主要用于创建Session对象。
sessionFactory负责解析和管理hbm.xml中的映射信息,
生成基本的预编译的SQL操作语句
3)Session
主要负责提供增删改查的操作方法
4)Transaction
负责管理hibernate操作的事务。
注意hibernate默认关闭了自动提交功能,
因此需要显式使用事务提交才能将数据写入db
5)Query
负责执行hibernate的HQL查询语句
*5.Hibernate基本使用步骤
利用Hibernate对COST表操作。
1)引入hibernate开发包+数据库驱动包
2)添加hibernate.cfg.xml主配置文件
3)编写Cost实体类
4)编写Cost.hbm.xml映射描述文件
--需要在hibernate.cfg.xml中添加<mapping>元素指定Cost.hbm.xml所在位置
5)利用hibernateAPI执行增删改查操作
按主键查询: session.load()/session.get()
添加操作:session.save(obj)
按id删除: session.delete(obj)
更新整个对象状态:session.update(obj);
==============================
第二天
===================
1.Hibernate映射类型
在hbm.xml中定义字段和属性映射时,type属性用于指定映射类型。
映射类型可以使用Java类型或者Hibernate类型。
映射类型作用是:实现字段值和属性值相互转化。
1)Java类型(完整包名.类名)
java.lang.Integer,java.lang.String等
2)Hibernate类型(推荐)
*a.字符串 string
*b.整数 byte,short,integer,long
*c.浮点数 float,double
*d.时间日期 date,time,timestamp
*e.布尔类型
yes_no : 实现boolean属性和Y|N值的 相互转化
true_false :实现boolean属性和T|F 值的相互转化
f.其它例如blob,clob,big_decimal,
big_integer
2.Hibernate主键生成方式
Hibernate在添加操作时,可以自动生成主键值,具体方式预定义了以下几种:
*1)sequence
采用序列方法生成主键值,仅适用Oracle
使用格式如下:
<generator class="sequence">
<param name="sequence">
序列名
</param>
</generator>
*2)identity
采用数据库自动增长机制生成主键值。适用于MySQL,SQLServer数据库。
需要建表时将主键字段设置成自动增长。
<generator class="identity">
</generator>
*3)native
根据dialect参数自动切换成identity或sequence方式。
4)assigned
hibernate不负责生成id,需要开发者在程序中指定id值。
5)uuid
采用uuid算法生成一个id值,值类型是字符串类型
6)hillo
采用高低位算法生成一个id值,类型是数值
7)increment
先执行select max(id)语句获取当前ID最大值,然后加1执行insert操作。适用于各种数据库
提示:如果上述生成方式都不能满足需要,可以自定义主键生成器。
(参考MyGeneratorId.java)
===========================
3.Hibernate框架基本特性
1)一级缓存(Session级别)
一级缓存默认开启。
当查询某一个对象时,第一次会查询数据库,
取回的对象会默认放入一级缓存,
如果再使用当前session查询该对象时,
会直接从缓存取出,减少了对数据库的查询。
当Session对象创建后,
每个Session都有一个独立的一级缓存区,
每个Session只能使用自己的缓存区,不能交叉访问。
在程序中可以利用以下方法清除缓存中的对象,释放空间。
session.evict(obj);// 清除指定的obj对象
session.clear();// 清除所有缓存对象
session.close();// 释放session及其缓存
2)对象持久性
在使用hibernate过程中,实体对象可以具有以下三种状态:
a.临时状态
使用new构造出来的。
*b.持久状态
与session对象关联,受session管理的对象。例如调用了load,get,save等方法后
持久状态的对象有以下特点:
--持久对象的数据状态可以与数据库同步更新。//one
--垃圾回收器不能回收持久对象//two
--持久对象存在于一级缓存中,受Session管理,由Session负责持久化操作的。//three
--持久对象同步更新是在session.flush时刻执行。//four
tx.commit()方法在内部先调用flush方法,
然后再执行事务提交动作
c.游离状态
原来是持久状态,当调用evict,clear,close后会变成游离状态
================================
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
for(int i=1;i<=10000;i++){
Foo foo = new Foo();
// setter
session.save(foo);
if(i % 50 == 0){
session.flush();// 同步,将缓存的数据和数据库进行同步
session.clear();// 释放缓存
}
}
tx.commit;
HibernateUtil.closeSession(session);
==============================
3)延迟加载
a.什么是延迟加载
当使用延迟加载方法时,返回的实体对象并没有数据库数据,
而是在使用对象的getter方法获取属性值时才去发送SQL操作,去数据库查询。
*b.什么操作采用加载机制
session.load()
query.iterator()
采用关联映射后,获取关联属性的getter
*c.避免出现以下异常
org.hibernate.LazyInitializationException:
could not initialize proxy - no Session
原因是采用了延迟加载机制的操作,但是在加载数据前关闭了Session导致的。
d.延迟加载的好处
主要优点是降低用户操作的并发率。
e.延迟加载实现原理
hibernate框架采用动态代理技术实现了延迟加载机制。
动态代理技术指的是:动态在内存中构建一个类型,动态的编译,
然后载入类加载器使用。Java中可以利用asm.jar,
cglib-2.1.3.jar.
asm可以动态生成一个类,动态编译。
cglib可以动态生成一个类的子类。
---------原理的过程如下---------
利用延迟加载方法返回的对象类型,是借助于cglib.jar工具动态生成的一个类型,
该类型是原实体类的子类。在动态生成的子类类型中,
重写了属性的getter方法。在重写的get方法中,会触发SQL查询操作。
public class Foo$$CGLIB23423
extends Foo{
public String getName(){
// 检查是否已加载数据,
// 没有的话,执行sql加载数据
// 有的话,将name值返回
}
}
*f.session中load和get方法区别如下
--load具有延迟加载机制;get没有,是立刻加载数据
--load返回一个动态生成类型的对象;get方法返回的是实体类对象
--load查询如果没有符合条件的记录会抛出ObjectNotFoundException;get没有结果返回的是null
==========综合练习=========
采用Hibernate技术改造原资费模块的增删改查功能。
=====================
第三天
==============
=====重构资费管理模块功能=======
*.action-->拦截器1-->Action
-->DAO-->Result(JSP)-->拦截器1
-->响应
*.OpenSessionInView模式控制Session关闭。
有些延迟加载的机制,在数据显示的时候(get)使用,如果过早关闭session会错误
该模式可以采用拦截器或Filter实现。
拦截器属于Struts2框架技术
Filter属于JavaWeb开发技术
拦截器和Filter执行时机不同
*.action-->Filter-->Struts控制器-->拦截器
=====================
1.关联映射
1)需求
需要查看1011账号信息,并且显示其下属的业务账号信息。
采用关联映射方式实现,具体方法如下:
a.一对多关系映射
建立Account-->Service方向的一对多关联
--首先在Account中添加一个集合属性,用于存放关联的Service对象. Set<Service>
--在Account.hbm.xml中,对集合属性添加映射描述信息。
//一对多描述信息
<set name="集合属性名">
<key column="指定关联的外键字段">
</key>
<one-to-many
class="要关联的另一方类型"/>
</set>
b.关联使用
Set<Service> services =
account.getServices();
通过调用getter就可以获取与当前Account对象相关的Service.
注意:关联属性数据默认采用延迟加载机制,而是在访问关联数据时才会进行数据的加载。
=====================================
第四天
========================
1.多对一关系映射
Service-->Account
1)在n方Service中添加一个属性,用于存储相关的Account
private Account account;
2)在Service.hbm.xml中利用下面格式描述
//多对一描述信息
<many-to-one name="属性名"
class="要关联的Account类型"
column="关联的外键字段"/>
3)删除Service中原关联字段accountId的映射和属性定义。
2.关联操作
1)join fetch查询
默认情况关联属性数据采用的是延迟加载。使用时才发送一个SQL查询关联表数据。
如果需要将关联属性的数据和当前主对象一起实例化,可以采用下面方法。
方法:采用HQL语句,使用join fetch查询
// 在查询a对象数据时,同时将services中的数据查询出来,采用表连接join形式用一个sql取出来
from Account a join fetch a.services;
2)级联操作
在建立关联映射后,采用级联操作,在对主对象做增删改时,
可以将关联属性中的数据也执行相应的增删改操作。
默认情况下,关联属性不支持级联操作,
需要在hbm.xml中定义关联属性映射时,
使用cascade属性,
该属性值可以为none,delete,save-update,all等
a.级联添加
需求:向Account写入一条,向Service写入两条记录
提示:需要Service对象给Account对象的关联属性services集合加入。
b.inverse属性的使用
默认情况下,在进行级联操作时,
hibernate框架为了维护相关对象之间的关系,
在级联操作后会对关联字段值进行更新操作
inverse属性作用是可以指定关系维护工作由哪一方来负责。
当Account中关系属性使用了inverse=true,
意思是在对Account执行操作时,不负责维护关系字段值,避免了update语句。
而是将关系维护交给了Service一方负责。
c.级联删除
在删除Account对象同时也删除相关的Service对象记录。
注意:删除的account对象需要通过session的load,get方法查询出来,不要采用new的方式。
3.多对多关系映射
提示:数据中由3张数据表才能表示多对多关系。需要由中间的关系表存储关联数据。
例如Admin_info,Admin_Role,Role
1)需求:显示某个管理员信息,并显示该管理员具有的角色信息
--建立Admin_info到Role的多对多关系
--首先在Admin中添加一个集合类型关联属性,用于存储相关的Role信息
--然后在Admin.hbm.xml中添加关联属性的描述
//多对多关系描述信息
<set name="属性名" table="中间关系表">
<key column="关系表与当前类型关联的字段">
</key>
<many-to-many class="要关联的数据类型"
column="关系表与class类型关联的字段"/>
</set>
==========================
第五天
=================
-----知识总结-------
1.(理论)Hibernate作用和设计思想
2.(应用)掌握对单表的基本操作
3.(理论)Hibernate的一级缓存、对象持久性、延迟加载机制
4.(应用)掌握OpenSessionInView模式控制事务和Session关闭
5.(应用)多对一映射、一对多、多对多映射
--能正确建立映射描述
--基于关系进行增删改查操作
(级联操作,join fetch查询)
=======================
1.如何利用Myeclipse生成hbm.xml和实体类
--进入DB Browser建立一个与数据库的连接
--新建一个开发工程,
点工程右键-->选择MyEclipse
-->Add Hibernate Capability....
(按提示界面,选择版本、创建主配置文件、定义连接参数、创建HibernateUtil)
--创建实体类和hbm.xml,
进入DB Browser,选择要生成的数据表,
右键-->Hibernate Reverse Engine...
(按提示界面,选择要生成的内容和存放工程、设置映射类型、定义实体类名和主键生成方式)
*2.继承关系映射
Hibernate可以将具有继承关系的对象映射到数据库。
继承关系映射Hibernate支持3种形式。
1)将父类和子类映射到一张数据表(略)
*2)将父类和子类分别映射到父类表,子类表
--修改实体类,将子类extends父类
--hbm.xml采用<joined-subclass>元素描述
<joined-subclass
name="子类类型"
extends="父类类型"
table="子类映射的表名">
<key column="子表的关联字段"></key>
</joined-subclass>
3)将父类和子类映射到子类表(略)
3.Hibernate查询
*1)HQL查询
Hibernate Query Language
HQL与SQL结构相似,但是SQL是针对数据表和字段进行查询,
而HQL是针对于hibernate映射过来的类型和属性进行查询。
因此HQL也被称为面向对象的查询语言。
HQL与SQL相似点如下:
--都支持select,from,where,
group by,order by,having等字句
--都支持<,>,>=,+,-,*,/等运算符和表达式
--都支持in,not in,between and等过滤条件
--都支持max,min,count,avg,sum等统计函数
HQL与SQL不同点如下:
--HQL大小写敏感,区分大小写
--HQL不支持select *写法
--HQL不支持join on中的on子句
HQL使用示例
--带查询参数的HQL,例如
from Account where idcardNo=?
from Account where idcardNo=:no
--查询部分字段值的HQL,例如
//默认采用Object[]封装一行记录
select id,realName from Account
//指定采用Account封装一行记录
select new Account(id,realName)
from Account
--将HQL定义到hbm.xml文件中
Query query =
session.getNamedQuery("标识符");
--分页查询
query.setFirstResult(抓取起点);
query.setMaxResult(抓取数量);
query.list();
2)Criteria查询
3)SQLQuery查询
select s.id,s.unix_host,s.os_username,
a.real_name,a.idcard_no
from Service s , Account a
where s.Account_Id=a.id
=======================
第六天
================
1.Criteria查询(QBC)
Criteria c = session.Criteria();
利用Criteria执行查询操作
*2.SQLQuery查询
执行原始的SQL语句
SQLQuery query =
session.createSQLQuery();
利用Query执行查询操作
3.二级缓存
二级缓存是SessionFactory级别,默认关闭,
二级缓存的对象可以被不同Session对象访问。
比较适合存储被多个不同用户频繁访问的对象,
该对象修改频率比较低的共享数据对象
1)二级缓存使用方法(适用3.2及其以上版本)
a.引入第三方提供的缓存组件
b.在hibernate.cfg.xml中启用二级缓存,指定缓存组件的驱动类
c.在要缓存的hbm.xml中添加<cache>元素
2)二级缓存的管理
如果需要立刻释放二级缓存空间,可以使用下面API
SessionFactory.evict();//移除缓存对象
4.查询缓存
一级和二级缓存只能缓存单个对象,像一个结果集或者一个值想缓存可以使用查询缓存。
1)查询缓存的使用方法
a.需要建立目标类型的二级缓存存储
b.在hibernate.cfg.xml中开启查询缓存
c.在执行query.list之前需要调用
query.setCahceable(true);
2)什么情况适合使用查询缓存
a.属于不同用户共享的数据,使用频率比较高
b.该数据更新操作频率比较低
c.需要将查询结果集缓存,数量不能太大
*5.锁机制
Hibernate提供了悲观锁和乐观锁机制,主要用于解决事务并发问题。
悲观锁机制:在用户查询数据时,加上锁,这样会阻止其他用户对该数据的增删改查。
只有当前用户线程将事务结束,锁会自动释放,此时其他用户线程才可以查询和操作。
session.load(Train.class,1,
LockMode.UPGRADE);
悲观锁采用的是数据库的锁机制实现。
悲观锁特点:安全性比较高,都可以顺序处理,但是处理请求的效率比较低。
乐观锁机制:允许不同用户都同时查询和更新相同数据,
如果发生事务并发,只有第一个做更新操作的用户会成功,后面的更新操作会失败。
Hibernate采用了一个版本号字段实现该机制。
如果查询出来的数据对象版本号相同,
第一个更新提交的用户会成功,成功后会将版本号加1,
这样后续提交的用户的版本号比数据库版本字段低,
hibernate会阻止后续更新操作
悲观锁和乐观锁特点:
悲观锁可以处理事务并发的各个请求。出现同时更新时,同步开,排队处理。
乐观锁只处理第一个,后续的会抛出异常失败。允许同时做更新操作。
===================================