Hibernate 学习资料

一. Hibernate基本概念

1. Hibernate框架的作用和特点

       Hibernate主要负责对数据库进行访问,它是对JDBC的封装。

2. Hibernate框架基本原理

       ORM--ObjectRelation Mapping 对象关系映射

       主要思想:将Java对象与关系表进行自动映射,这样可以直接将对象更新到数据库;查询时可以自动将数据库表记录封装成Java对象。

       Hibernate框架基于ORM原理实现,Hibernate是目前主流的ORM工具,此外还有MyBatista,JPA等。

3. Hibernate主要的体系结构

       实体类(Xx):

              可以有N个,与数据库中的表对应,用于封装数据库表的一行记录。

       XML映射文件(Xx.hbm.xml):

              可以用N个,主要描述实体类与数据库表之间的对应关系;类属性对应表字段。

       主要配置文件(hibernate.cfg.xml):

              可以有1个,用于指定连接数据库的参数,框架参数等。

4. Hibernate核心API

       a:Configuration :用于加载主配置文件和映射文件

       b:SessionFactory :用于创建Session对象

       c:Session :原Connection对象的封装,代表Hibernate与数据库之间的一次连接,负责执行增删改查操作。

       d:Transaction :用于进行事务管理,由于自动提交功能,默认被Hibernate关闭,因此使用时必须显式commit操作。

       e:Query :负责执行各种查询。

5. Hibernate生成主键的方式

       常用的生成主键的方式有如下几种:

              identity:用于自动生成主键方式,除了Oracle不支持,其他数据库一般都支持。

       <generatorclass=”identity”></generator>

              sequence:Oracle中使用,用序列(sequence)生成ID主键

       <generatorclass=”sequence”>

              <paramname=”sequence”>指定列名</param>

</generator>

              native:生成主键的方式如果是native则表示由Hibernate决定,Hibernate会根据配置文件hibernate.cfg.xml中方言<propertyname="dialect">是什么,如果方言是Mysql,相当于identity,如果方言是Oracle,相当于sequence。

              <generatorclass=”native”></generator>

              <generatorclass=”native”>

                     <paramname=”sequence”>指定列名</param>

</generator>

              increment:取出现有表中的主键的最大值,家1后作为新的主键值,不常用;

不安全,容易产生并发冲突(若并发操作几率较高时不建议使用)

              assigned:手动生成id,也就是需要程序中定义一个主键,不常用。

              其他:UUID,hilo(高低位算法)

6. 数据映射类型

7. Hibernate对象状态:

       暂时态:Transient

使用new操作符初始化的对象的状态是瞬时的,如果没有任何跟数据库表相关联的行为,只要应用程序不再引用这些对象,它们的状态将会丢失,并由垃圾回收机制回收,这种状态被称为暂时态。

       持久态:persistent

如果内存中的对象和数据库的记录有对应关系,即和session对象相关,则此对象处于persistent状态,当事务提交时它们的状态和数据库进行同步。

游离态:Detached

Session关闭之后,持久化对象就变为detached对象,表示这个对象不能再与数据库保持同步,它们不再受Hibernate管理。

另外当调用了session.evic(Objectobj)方法,对象和session解除了关系,也将处于游离态。

 

二. 缓存:

8. 一级缓存(session级别缓存):

(1)      如果通过session查询某对象,session先到缓存中查找是否有被查询的对象,找到则直接取出,否则才查询数据库。

(2)      Session需要负责实时维护在缓存中的数据,保证缓存中的数据与数据库中数据的一致性,一旦用户对缓存中的数据作了修改,session负责将数据更新到数据库中。

缓存的好处:减少对数据库的访问次数。

 

提示:

       A:同一个session访问一个对象多次,只能对数据库访问一次。

       B:每个session只能访问自己的缓存区,不能交叉访问。

       C:同一个session访问不同的对象,查询数据库多次。

 

缓存的生命周期:

              Session创建,缓存创建;

              Session关闭,缓存释放。

      

循环多次不及时释放缓存会发生内存溢出异常。

Eg:

              for(Stringid : ids){

                            Foofoo = (Foo)session.load(Foo.class,id);

session.evict(foo);// 应及时释放缓存

}

 

 

       Session.clear();  //清除缓存中的所有对象

       Session.close();//关闭缓存

 

9. 延迟加载

       A:延迟加载:在使用Hibernate方法查询数据库对象时,Hibernate返回的对象没有立刻加载数据库中的数据,而是使用对象的getter方法触发SQL查询语句,去数据库端执行返回数据库内容。

       B: 什么操作具有延迟加载:

       (1) session.load()

       (2) query.iterator()

       (3)关联属性加载

       C:注意:采用延迟加载机制要避免session关闭过早,如果session关闭过早会发生下面异常:

       Org.hibernate.LazyInitialization:cloudnot initialize proxy-no session.

遇到异常,解决方法:

(1)      采用非延迟加载机制的操作:

eg: session.get()      query.list()等

(2)      将session关闭放到POJO对象使用之后(推荐使用)

(3)      在项目中常使用OpenSessionInView模式控制session关闭。

 

 C:延迟加载的好处:

              可以提升内存资源的使用率

              可以降低对数据库的并发访问

D:OpenSessionInView实现方法:

            Servlet—过滤器

            Struts2—拦截器

            Spring—AOP

E:OpenSessionInView和ThreadLocal

使用OpenSessionInView必须满足Session的线程单例:一个线程分配一个session,在该线程的方法中可以获得该session,具体事宜ThreadLocal—其实是一个线程为key的map,

Hibernate支持的session线程单例

       配置文件中:

       <propertyname=”current_session_context_class”>thread</property>

       然后调用:

       sessionFactory.getCurrentSession()

自动实现线程单例。

 

三. 关联映射

1. Hibernate关联映射作用

       如果数据表之间有关联字段,都可以采用Hibernate关联映射在POJO之间建立关系,这样在Java代码里可以通过POJO之间的关系进行数据的增删改查等级联操作。

 

2. 如何建立关联映射

       --前提:表之间有关联字段

       --然后:判断表之间的关联属性

       --then:在POJO实体类中添加关联属性

       --end:在hbm.xml中描述属性的映射信息。

3. 一对多关联(one-to-many)

       1) 关联条件(根据E-R和表说明文档)

              accout_id(主键,1)   service.accout_id(外键,n)

       2) 关系类型(根据需求)

              accout-àservice是一对多关系

       3)追加POJO属性

       要根据Accout对象,找出相关service信息。因此需要建立accout——>service的一对多关联映射。在Accout中添加关联属性,将通过该属性的getter方法获取相关的service。

       4) 在hbm.xml中描述相关属性

       <setname=”service”>

              <keycolumn=”account_id”></key> // 用于指定关联条件,写关联条件的外键字段

              <ont-to-manyclass=”POJO.Service” /> //用于指定采用哪种关系,加载哪方数据

       </set>

4. 多对一(many-to-one)

       多对一映射描述:

       <mang-to-one

name=”account”

column=”account_id”

class=”POJO.Account”>

</many-to-one>

 

5. 关联操作

       1) 关联查询

默认:关联属性数据采用延迟属性加载,单独发送一个SQL语句查询关联数据;

       如果需要当前对象和关联属性一起采用一个SQL语句,可以采用下列方法:

              A:修改hbm.xml

       Lazy属性:默认是true(延迟加载),false表示关闭延迟加载

Fetch属性: join表示采用表连接方法对主对象一起查询

Select(默认)表示单独发送一个sql关联数据

              B:编写HQL,使用join fetch关键字

              Fromaccount a join fetch a.service where a.id=?

上述HQL在调用Account对象时,将service关联属性数据采用表连接方法并查。

 

       2) 级联添加

当执行session.save(account)如果将service关联属性设置了级联操作,那么除了将Account写入数据库Account之外,也会将Service中的service对象写入数据库Service表中。

       使用注意事项:

              A:需要在关联属性hbm.xml描述中添加cascade属性,指定级联操作类型

                            None:默认,不支持级联操作

                            Save-update:支持级联操作的添加和更新

                            Delete:支持级联删除

                            All:支持级联添加,更新,删除

              B:将关联对象放到关联属性中,指定关联关系

       3) inverse属性

默认情况下Account和Service对象之间的关系由双方负责维护工作:就是对Account和Service对象做级联操作时需要执行update语句。

       将关联字段设置相同id,如果需要取消某一方的关系维护工作,可以在关联属性映射部分添加inverse=“true”设置,这样可以避免update语句执行。

       提示:inverse=“true”通常加在<ont-to-many>映射部分,这样在对象级联操作时可以避免大量update。

 

       4)级联删除

              Session.delete(obj)obj需要持久对象,不能new,需要load/get取出。

 

批量删除方法:

级联删除采用n+1个delete语句清除主表和外键表的关联数据。如果是批量删除,不推荐级联删除,建议使用HQL编写delete语句。

例如:

Delete fromService where account.id=?

Delete fromAccount where id=?

 

6. 多对多关系

Admin-info           admin_role            role

1)     关系建立

A)在POJO中添加set集合属性

B)在hbm.xml中添加属性的映射描述

<set  name=”roles” table=”admin_role”> //roles 属性名  admin_role   中间关系表id

       <key column=”admin_id”></key>  //关系表与当前class关联字段

       <many-to-many  class=”POJO.Role”  column=”role_id”>

</many-to-many>

</set>

 

四. Hibernate查询

 

1.  Hibernate提供的数据库访问方式:

1) HQL(Hibernate Query Language)

属于面向对象查询语句,针对Hibernate映射过来的POJO进行查询,实现对数据库的查询。

       2)  HQL与SQL相比

A)相似点:

1) HQL支持SQL中的select ,where ,from ,group by , having ,order by 等字子句。

2) 支持SQL中的> , <, >= , <= ,in , not in, between ,and  ,like等查询条件子句。

B)不同点:

1)     HQL区分大小写(关键字不区分)

2)     HQL语句使用的是POJO类型名和属性名,不能使用表名和字段名

3)     HQL不支持select * 写法,但支持 select count(*) 写法

From user /     select u from user u

4)       HQL不支持join  on 中的on子句

5)       HQL不支持数据库函数

Eg:字符函数,日期函数 to_date     to_char

              6)

2. Hibernate高级特性

       1)  二级缓存(默认是关闭的)

              二级缓存是SessionFactory级别的,由SessionFactory对象管理。

特点:

              ——可以跨越session,不同session对象可以可以访问同一二级缓存空间。

适用环境:

              ——对象数据频繁访问(共享),对象数据更新频率低

使用方法:

              ——引入ehcache.jar,在src下添加ehcache.xml缓存配置文件

              ——在Hibernate.cfg.xml中开启二级缓存,指定采用二级缓存组件的驱动

              ——在要缓存的POJO的hbm.xml中添加<cache>元素

                     <cache usage=”read-write”region=”simplecache”>    

2)     查询缓存(默认关闭)

一二级缓存只能换存单个对象,如果遇到某个字符串结果,数组结果或者List集合,可以使用查询缓存。

使用方法:

        ——缓存结果:对象类型,首先要启用二级缓存

        ——在Hibernate.cfg.xml中开启查询缓存

        ——在执行query.list()之前设置query.setcacheable(true)

        提示:查询缓存是以二级缓存为基础,需要首先开启二级缓存。

使用环境:

        需要频繁执行相同的查询语句

        查询结果集内容改变频率小

        结果集数量不要太多

提示:相同SQL,第一次去数据库查,后续从缓存中查,缓存的是SQL+结果集

 

 

        一级缓存:单用户

        二级缓存:多用户

        查询缓存:多用户的结果集

3)事务并发处理

       两种处理事务并发的方法:悲观锁和乐观锁

1)    悲观锁

在查询数据时枷锁,其他线程不能对该数据作任何操作,当前事务结束后其他线程才可以访问。

Hibernate本身没有提供悲观锁实现,而是采用数据库锁机制实现的。

Session.load(Service.class,LockMode.UPGTADE);

在发生sql语句时,添加forupdate关键字,这样数据库就会锁住当前记录。

       特点:安全性高,因为是排他处理,需要依次排队处理,因为处理效率低。

 

2)    乐观锁

在用户并发量很高的情况下,可以提高处理效率。当多个用户同时对某个对象做更新操作时,第一个更新操作提交的用户会成功,后需提交的用户失败。

 

               该机制借助一个版本字段实现,当第一个用户更新提交后,Hibernate会将该字段更新+1,这样后续用户提交的对象版本字段比数据库中的小,会抛出异常。

               乐观锁的使用方法:

        ——为数据库中添加一个版本字段t_version

        ——在POJO对象中添加一个version属性。

        ——在hbm.xml文件中,利用<version>定义版本控制字段。

 

悲观锁和乐观锁的选择:

        如果并发用户排他处理,一个成功,其他失败选择乐观锁。

        如果对并发用户依次处理,都完成具体操作,可以选择悲观锁。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值