论坛首页 Java企业应用论坛

复习 - 持久化环境相关的其他API (clear, evict, setReadyOnly)和FlushMode

浏览 2016 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-03-24  

复习 - 持久化环境相关的其他API (clear, evict, setReadyOnly)和FlushMode

 

前面的一些复习提到了Hiberante的自动脏数据检查功能,他的实质是会保存对象的一个快照,这个功能固然很好很强大,但是一旦数据量比较大,那么快照所需的空间也会比较大,所以我们可能需要在合适的时候进行手动的清理,来确保不会OutOfMemory

 

有下面几种可以清理的session中的对象或是阻止生成快照的方法

 

1. evict

这个方法就是将session中的对象(persist状态)清理出去,让他变成detached状态. 这样在session级别的缓存中就不会有该对象存在,如果查询同一条数据库中的数据,会重新生成查询语句加载,例子如下:

 

package com.yxy.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.yxy.bean.Student;

public class HibernateClearTest {
	
	public static void main(String[] args){
		
		SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
		Session session = sessionFactory.openSession();
		session.getTransaction().begin();
		
		Student s1 = (Student)session.get(Student.class, 1);
		
		session.evict(s1);		
		
		Student s2 = (Student)session.get(Student.class, 1);
		
		session.getTransaction().commit();
		session.close();
	}
}

 

 可以在控制台看到加载s2,虽然对应的是数据库中的同一条记录,但是重新生成了select语句,说明一级缓存中的对象已经被清理出去了.

 

Hibernate: 
    /* load com.yxy.bean.Student */ select
        student0_.id as id0_0_,
        student0_.name as name0_0_,
        student0_.sex as sex0_0_,
        student0_.register_date as register4_0_0_ 
    from
        student student0_ 
    where
        student0_.id=?
Hibernate: 
    /* load com.yxy.bean.Student */ select
        student0_.id as id0_0_,
        student0_.name as name0_0_,
        student0_.sex as sex0_0_,
        student0_.register_date as register4_0_0_ 
    from
        student student0_ 
    where
        student0_.id=?
 

 

2. clear

clear针对的是session中的所有对象. 原理同evict一样,同样的是让所有persist状态的对象全部变成detached状态,移出persistent context环境. 这样就不会对该对象生成快照,从而避免了脏数据检查. 节省了空间, 例子:

 

package com.yxy.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.yxy.bean.Student;

public class HibernateClearTest {
	
	public static void main(String[] args){
		
		SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
		Session session = sessionFactory.openSession();
		session.getTransaction().begin();
		
		Student s1 = (Student)session.get(Student.class, 1);
		
		session.clear();
		
		s1.setName("update detached object");
		
		session.getTransaction().commit();
		session.close();
	}
}

 

 从控制台可以看到没有生成update sql,仅有一条加载的sql, 而且数据库中的数据也没有被更新,这是因为s1已经是detached状态,当事务提交时并不会对detached状态的对象进行检查,所以更新不会同步到数据库中.

 

Hibernate: 
    /* load com.yxy.bean.Student */ select
        student0_.id as id0_0_,
        student0_.name as name0_0_,
        student0_.sex as sex0_0_,
        student0_.register_date as register4_0_0_ 
    from
        student student0_ 
    where
        student0_.id=?
 

 

3. setReadOnly

顾名思义,setReadOnly会将对象设置成只读的,所以hiberante不会因为对该对象做了update就对其进行脏数据检查从而同步到数据库,Hiberante不会对设置成readonly的对象做脏数据检查,但是设置成只读的对象并没有在session中被清除掉,不像clear和evict那样.  

例子:

 

package com.yxy.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.yxy.bean.Student;

public class HibernateClearTest {
	
	public static void main(String[] args){
		
		SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
		Session session = sessionFactory.openSession();
		session.getTransaction().begin();
		
		Student s1 = (Student)session.get(Student.class, 1);
		
		/*
		 * set to read only
		 */
		session.setReadOnly(s1, true);
		
		/*
		 * s1 will not be removed from session cache, so when call this statement, no need load again.
		 */
		Student s2 = (Student)session.get(Student.class, 1);
		
		/*
		 * because s1 is read only, so will not flush this update to db when the transaction is commit
		 */
		s1.setName("update detached object");
		
		session.getTransaction().commit();
		session.close();
	}
}

 

 可以看到生成的log不会重复加载,也不会生成update sql

 

Hibernate: 
    /* load com.yxy.bean.Student */ select
        student0_.id as id0_0_,
        student0_.name as name0_0_,
        student0_.sex as sex0_0_,
        student0_.register_date as register4_0_0_ 
    from
        student student0_ 
    where
        student0_.id=?
 

 

另外,就是要记住Hibernate的几种FlushMode

1. FlushMode.AUTO

特点: 是Hibernate的默认行为, 当事务被提交或者是发生查询时,会flush脏数据到db

 

2. FlushMode.COMMIT

特点: 只有在事务被提交或调用session.flush()才会flush脏数据到db


3. FlushMode.MANUAL

特点: 只有在调用session.flush()时才会flush脏数据到db.

   发表时间:2011-03-28  
楼住,FlushMode在那里设置的?默认值是什么?
0 请登录后投票
   发表时间:2011-03-28  
21jhf 写道
楼住,FlushMode在那里设置的?默认值是什么?



是在Java代码里面设置的,像这样

session.setFlushMode(FlushMode.COMMIT)
 默认的级别是FlushMode.AUTO, 也就是事务被提交或者发生查询之后才会将脏数据同步到db里面.  

 

 

0 请登录后投票
   发表时间:2011-03-28  
spring-china 写道
21jhf 写道
楼住,FlushMode在那里设置的?默认值是什么?



是在Java代码里面设置的,像这样

 

session.setFlushMode(FlushMode.COMMIT)
 默认的级别是FlushMode.AUTO, 也就是事务被提交或者发生查询之后才会将脏数据同步到db里面.  

 

 

谢谢

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics