Hibernate:Session详解

session概述

Session 接口是 Hibernate 向应用程序提供的操纵对数据库的最主要的接口, 它提供了基本的保存, 更新, 删除和加载Java 对象的方法.

理解session的缓存

l  在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存. 只要 Session 实例没有结束生命周期, 存放在它缓存中的对象也不会结束生命周期

l      当session的save()方法持久化一个对象时,该对象被载入缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中。当试图load()对象时,会判断缓存中是否存在该对象,有则返回。没有在查询数据库。

清理session的缓存

l  Session 具有一个缓存, 位于缓存中的对象称为持久化对象, 它和数据库中的相关记录对应.Session 能够在某些时间点, 按照缓存中对象的变化来执行相关的 SQL 语句, 来同步更新数据库, 这一过程被称为清理缓存(flush)

l  默认情况下 Session 在以下时间点清理缓存:

•    当应用程序调用 Transaction 的 commit()方法的时, 该方法先清理缓存(session.flush()),然后在向数据库提交事务(tx.commit())

•    当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生了变化,会先清理缓存,以保证查询结果能够反映持久化对象的最新状态

•    显式调用 Session 的 flush() 方法.

区别:

     flush:进行清理缓存(此时缓存中的数据并不丢失)的操作,让缓存和数据库同步 执行一些列sql语句,但不提交事务,;

     commit:先调用flush() 方法,然后提交事务. 则意味着提交事务意味着对数据库操作永久保存下来。

     reresh:刷新,让session和数据库同步,执行查询,把数据库的最新信息显示出来,更新本地缓存的对象状态.

     clear:清空缓存,等价于list.removeAll();

利用Session缓存读取持久化对象的数据

1  Customer c = new Customer(“TOM”,new HashSet());

2  session.save(c); //customer对象被持久化,并且加入到session的缓存中

3  Long id = c.getId();

4   c= null; //c变量不再引用customer对象

5  //从session缓存中读取customer对象,使c2变量引用customer对象

6  Customer c2 = (Customer)session.load(Customer.class,id);

7  tx.commit();  //缓存中的对象和数据库同步

8  session.close(); //关闭session 清空缓存

9   System.out.println(c2.getName());//访问customer对象

10 C2 = null; //C2对象不再引用customer对象,customer对象结束生命周期

---------------------------------------------------------------------------------------------

缓存的作用:

1。减少访问数据库的频率。

2。保证缓存中的对象与数据库中的相关记录保持同步。

Session执行批量操作

可以写一个for循环,Session可以批量插入上万条数据。如下面的代码:

            For(int i=0;i<10000;i++){

           Session.save(object);

}

这样写的代码会产生一个什么问题?会使一万个对象的缓存全部存在于内存中,这样做加大了内存的压力。所以应该定期清理session的缓存,也就是flush和clear一下,这样内存才能保证足够的空间。

 

 Session.load与session.get方法

不同场合的不同解决方案

      场合一:当用户要取数据库的一张表的一个字段,这个字段很可能就是一个字符,总而言之长度是比较短的。(get)

      场合二:当用户要取数据库的一张表的一个字段的值,而这个值很可能是blob类型,也许存取的是一个很大的视频文件。(load)

       get和load主要的区别在于数据库中没有数据的时候,get返回null,而load抛出异常;另外一个就是对lzay-load的不同反应,get不支持lazy-load,load支持。

延迟加载

    也叫懒加载,不是在执行获取操作时马上生成SQL,而是在第一次使用时生成SQL。
    分成两种:
        类级别的:
            <class ... lazy="true/false">
        属性级别的:
            <set/list/map/bag ... lazy="...">
            <many-to-one ... lazy="...">
            <one-to-one ... lazy="...">
    在使用懒加载特性时,可能会有LazyInitializationException异常:
        原因:    
            真正的去获取数据时,Session已经没有了。
        解决办法:
            方式一:让Session在真正加载后再关闭。
            方式二:或是在Sessoin关闭前执行Hibernate.initialize(department.getEmployees());

集合的延迟加载

True   false   extra

extra为更进一步的延迟加载策略。

当调用getStudents()时不会加载hql语句,当加载student的属性的时候才会发出SQL语句

调用getStudents().size()方法的时候,会触发类似于:Hibernate: select count(id) fromT_Student where classid =? 这样的SQL查询语句(这是一种很聪明的做法,如果lazy=”true”,getStudents().size()将会使得hibernate加载所有集合的数据到内存中)。

调用getStudents().contains()方法的时候(即判断是否包含某个对象),会触发类似于:select 1 fromT_Student where classid =? and id =? 这样的SQL查询语句。


默认的检索策略是立即检索。在Hibernate映射文件中,通过在<class>上配置 lazy属性来确定检索策略。对于Session的检索方式,类级别检索策略仅适用于load方法;也就说,对于get、qurey检索,持久化对象都会被立即加载而不管lazy是false还是true.一般来说,我们检索对象就是要访问它,因此立即检索是通常的选择。由于load方法在检索不到对象时会抛出异常(立即检索的情况下),因此我个人并不建议使用load检索;而由于<class>中的lazy属性还影响到多对一及一对一的检索策略,因此使用load方法就更没必要了。

关联级别检索策略

fetch

(默认值select)

Lazy

(默认值是true)

策略

Join

False

采用迫切左外联接检索。

Join

True

采用迫切左外联接检索。

join

Extra

采用迫切左外联接检索。

select

False

采用立即检索

select

True

采用延迟检索

select

Extra

采用延迟检索

c.getOrders().size()  执行 select count(id) from orders where customer_id =?

for(Order o:set){ o.getOrderNumber();} 将执行:

select customer_id , id,order_number ,price from orders  where customer_id=?

subselect

false/true/extra

也分为3中情况

嵌套子查询(检索多个customer对象时) Lazy属性决定检索策略)

select customer_id,order_number,price from orders  where customer_id

         in (select id from customers)

 

检索策略

优点

缺点

优先考虑使用的场合

立即检索

对应用程序完全透明,不管对象处于持久化状态还是游离状态,应用程序都可以从一个对象导航到关联的对象

(1)select语句多

(2)可能会加载应用程序不需要访问的对象,浪费许多内存空间。

(1)类级别

(2)应用程序需要立即访问的对象

(3)使用了二级缓存

延迟检索

由应用程序决定需要加载哪些对象,可以避免执行多余的select语句,以及避免加载应用程序不需要访问的对象。因此能提高检索性能,并节省内存空间。

应用程序如果希望访问游离状态的代理类实例,必须保证她在持久化状态时已经被初始化。

(1)一对多或者多对多关联

(2)应用程序不需要立即访问或者根本不会访问的对象

迫切左外连接检索

(1)对应用程序完全透明,不管对象处于持久化状态还是游离状态,都可从一个对象导航到另一个对象。

(2)使用了外连接,select语句少

(1)可能会加载应用程序不需要访问的对象,浪费内存。

(2)复杂的数据库表连接也会影响检索性能。

(1)多对一

(2)需要立即访问的对象

(3)数据库有良好的表连接性能。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值