hibernate缓存机制(三)

对象的持久化状态:hibernate中的缓存:1)一级缓存  2)二级缓存
一级缓存:内置缓存 Session缓存 –---是必须用的!
   缓存的工作的底层原理:
执行session.save(c1) 这个过程中:
Session下的save函数会把c1这个对象做一个快照(snapshot),然后它会生成SQL语句把c1这个对象插入到数据库进行持久化,紧接着session下面的函数save会把c1的原对象扔到hibernate的一级缓存当中。
快照的含义:在save函数中通过克隆的技术反射出这个java对象并且将它存放到session下List<Map>这样一个成员变量中!
一级缓存:在session类下又做了一个成员变量List它把插入数据库的这个对象c1掉一个list.add(c1);把c1缓存起来!
通过代码的模拟如下:
class Session
{
    private List list = new ArrayList();
private List snapList = new ArrayList();
   public void save(Object obj)
   {
      //首先做一个快照
      Object objClone = obj.clone();
     snapList.add(objClone);
     //接着生成SQL语句将数据持久化到数据库
     Inser into(。。。。。);
      //然后将原对象保存到一级缓存当中。
      list.add(obj);
     
   }
}
 
当利用Session对数据进行持久化DML操作的时候一级缓存就被启用了!
缓存的含义:
Customer c1=new Customer(“Tom”,new HashSet());
session.save(c1);
Long id=c1.getId();
c1=null;//但垃圾回收不会回收c1这个对象,因为它在hibernate的一级缓存当中已经不属于JVM垃圾回收机制的管理了了。
Customer c2=(Customer)session.load(Customer.class,id);
//load方法去做数据库的查询操作,首先它会去一级缓存当中找id并且将这个对象查询出来,若一级缓存没有他才去数据库当中查询,并且查询出来的对象也会放在一级缓存当中!。
所以说一级缓存的做用就是为了减少访问数据库的频率,使内存的操作速度快
tx.commit();
session.close();
Session缓存的声明周期是很短暂的:session.close()缓存就会失效-----这个过程叫做缓存清空:
   在这个过程当中hibernate会把一级缓存当中的java对象和它记录的这个快照之中的成员变量挨个的进行一个对比如果发生变化,它就会自动的生成Update语句将数据做个更新然后存放到数据库当中。例如原来快照中存放的人名叫张三,执行完了session.save(c1);这条语句,紧接着又执行 c1.setName(“LiSi”);这个时候一级缓存(内存)当中的人名变成了LiSi 在清理缓存的时候,hibernate会将一级缓存 中的java成员变量和快照中对象的成员变量做个比较---把zhangsan更新为lisi持久化到数据库.
 
;
 
Session缓存的做用:
v      减少访问数据库的频率;(内存操作的速度快)
 
v      保证缓存中的对象与数据库中的相关记录保持同步。当持久化对象的状态发生改变,Session并不会立即执行相关的SQL语句,这使得Session可以把几条相关的SQL合并为一条,来减少访问数据库的次数。
 
v      Session加载对象时,会为对象做一个快照,当清理缓存时,会与这个备份进行比较,来决定做什么样的数据库操作。
 
Session是么时候清理缓存?
v      程序调用Transaction的commit()方法时,commit()方法先清理缓存,在提交数据库的事务
 
v      程序调用session的find()或者iterate()时,如果缓存中的持久化对象的状态发生了变化,就会先清理缓存,保证查询结果能反映持久化对象的最新状态
 
v      当应用程序显示的调用Session的flush()方法时
Hibernate应用中java对象的状态
v      临时状态(Transient):也叫瞬时状态。new出来的对象,没有被持久化处理,不处于Session缓存中的对象
 
v      持久化状态(Persistent):已经被持久化,加入到Session的缓存中
 
v      游离状态(Detached):也叫脱管状态。已经被持久化,但是不处在Session缓存中
例如下面的代码:
Customer c1=new Customer(“Tom”,new HashSet());//c1---临时状态
 
session.save(c1);
 
Long id=c1.getId();//c1------持久化
c1=null;
Customer c2=(Customer)session.load(Customer.class,id);
//c2-----持久化(从一级缓存当中查询出来的对象)
tx.commit();
 
session.close();
 
System.out.println(c2.getName());
//c2-----游离状态(session都关闭了)
 
c2=null;
总结:
v   从上面的程序可以看出,Session的save方法会使得Java对象的状态转变成持久化状态;Session的close方法会使得Java对象的状态转变为游离状态;
 
 
v   只要处于临时状态和游离状态的Java对象不再被任何变量引用,其就结束了其生命周期;但是处于持久化状态对象不然,由于缓存还在引用这个对象,所以其还处于生命周期
 
临时对象的特征:
v   不处于Session缓存中(不被任何一个Session实例关联)
 
v   在数据库中没有对应的记录
 
v   进入临时状态的条件:
new一个Java对象,他处于临时状态,不和数据库有任何记录关联
Session的delete方法能够使一个持久化对象或游离对象转变为临时状态;对于游离对象,delete方法从数据库中删除与它对应的记录;对于持久化对象,delete方法从数据库中删除与它对应的记录,并把它从session缓存中删除
 
持久化对象的特征:
v   在一个Session实例的缓存中(与一个Session关联)
 
v   持久化对象和数据库中的相关记录对应
 
v   Session清理缓存时,会根据持久化对象的属性变化,来同步更新数据库
 
v   进入持久化状态的条件
§                          session的save方法
§                          session的load和get方法返回的对象都是处于持久化状态
§                          session的find方法返回的List中存在的对象都是处于持久化状态
§                          session的update、saveOrUpdate和lock方法使得游离对象转换为持久化状态
§                          当一个持久化对象关联一个临时对象,在允许级联保存的情况下,Session在清理缓存时把这个对象也转变为持久化状态
 
游离对象的特征:
v   不再位于session缓存中(游离对象不被Session关联)
v   游离对象是从持久化对象转变过来的,因此在数据库中可能还存在与其对应的记录
v   游离对象与临时对象的区别在于:前者是由持久化对象转变过来的,并且在数据库中还存在与之对应的记录,而后者在数据库中没有与之对应的记录;
v   进入游离状态的条件
§                          当调用session的close方法的时候,session缓存被清空,缓存中的所有持久化对象都变为游离状态。如果此时再没有其它变量引用的时候,其生命周期结束
§                          session的evict方法能够从缓存中删除一个持久化对象,使它变为游离状态。如果内存中存在大量的对象的时候,可以通过这个方法来删除缓存中的对象(不建议使用这个方法,还是使用查询的方法和常规方法来处理对象在内存中的深度)
 
 
比较一下,下面的两个程序之间有是么区别?
Customer c=new Custoemr();
c.setName(“tom”);
session.save(c);
tx.commit();
 
Customer c=new Custoemr();
session.save(c);
c.setName(“tom”);
tx.commit();
v      以上两段对数据库的操作,虽然完成相同的功能,但是,生成的SQL语句却不同。
 
v      第一个生成一条insert语句,将customer对象存储到数据库中;而第二段代码生成两条SQL语句,一条insert和一条update
 
总结:
v      对象的OID来维持对象和数据库记录之间的对应关系。当Customer对象处于持久化状态的时候,不允许改变OID的值。
 
v      Customer c=new Customer();
    session.save(c);
    c.setId(new Long(6));//HibernateException
 
v      session的save方法是用来持久化一个临时对象,程序中不应该把持久化对象和游离对象传给save方法(多余的操作)
 
  Session的update方法
 
v      使一个游离对象转变成持久化对象
 
v      把对象重新加入到缓存中,使它变为持久化对象;计划执行update语句,在清空缓存的时候真正的执行SQL
 
v      class的select-before-update属性;如果想要session仅仅在对象的属性发生变化的时候才执行update,可以把这个属性设置为true;但是这个属性会在执行update操作之间,执行一个select操作(这样会对数据库多一次查询操作,所以要根据需求来选用这个属性)
 
Session的saveOrUpdate方法
v      包含了save和update方法的功能,如果传入的参数是临时对象,就调用save方法;如果传入是游离状态,就调用update方法;如果传入的对象是持久化对象,就直接返回;
 
 
v      Hibernate判断临时对象的标准:
§         Java的OID取值为null
§         Java对象具有version属性,并取值为null
§         映射配置文件id元素设置了unsaved-value属性,并且OID的取值与unsaved-value取值匹配
§         自定义了Hibernate的Interceptor实现类,并且Interceptor的isUnsaved方法返回Boolean.TRU
原文地址:http://blog.csdn.net/joe_007/article/details/6959126

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值