Hibernate旅程(三)Hibernate持久化对象的三个状态(一)

2014-11-24 02:40:41 · 作者: · 浏览: 0


Hibernate中的对象有3中状态,瞬时对象(TransientObjects)、持久化对象(PersistentObjects)和离线对象(DetachedObjects也叫做脱管对象)。


下图3.1显示了瞬时对象、持久化对象和离线对象之间的关系以及它们之间的转换。


\

图3.1


临时状态:由java的new命令开辟内存空间的java对象也就是普通的java对象,如果没有变量引用它它将会被JVM收回。临时对象在内存中是孤立存在的,它的意义是携带信息载体,不和数据库中的数据由任何的关联。通过Session的save()方法和saveOrUpdate()方法可以把一个临时对象和数据库相关联,并把临时对象携带的信息通过配置文件所做的映射插入数据库中,这个临时对象就成为持久化对象。


持久化状态:持久化对象在数据库中有相应的记录,持久化对象可以是刚被保存的,或者刚被加载的,但都是在相关联的session声明周期中保存这个状态。如果是直接数据库查询所返回的数据对象,则这些对象和数据库中的字段相关联,具有相同的id,它们马上变成持久化对象。如果一个临时对象被持久化对象引用,也立马变为持久化对象。

如果使用delete()方法,持久化对象变为临时对象,并且删除数据库中相应的记录,这个对象不再与数据库有任何的联系。

持久化对象总是与Session和Transaction关联在一起,在一个session中,对持久化对象的操作不会立即写到数据库,只有当Transaction(事务)结束时,才真正的对数据库更新,从而完成持久化对象和数据库的同步。在同步之前的持久化对象成为脏对象。

当一个session()执行close()、clear()、或evict()之后,持久化对象就变为离线对象,这时对象的id虽然拥有数据库的识别值,但已经不在Hibernate持久层的管理下,他和临时对象基本上一样的,只不过比临时对象多了数据库标识id。没有任何变量引用时,jvm将其回收。


脱管状态:Session关闭之后,与此Session关联的持久化对象就变成为脱管对象,可以继续对这个对象进行修改,如果脱管对象被重新关联到某个新的Session上,会在此转成持久对象。

脱管对象虽然拥有用户的标识id,所以通过update()、saveOrUpdate()等方法,再次与持久层关联。



下面我们就通过使用hibernate,实现对数据库的增删改查来体现三种状态之间的转换过程。


添加修改演示三种状态之间的变化


当我们建立Session都要实例化SessionFactory,所以我们把重复的代码进行封装,并且session是单线程的。我们把对session的管理,打开session,关闭session等封装到工具类中,代码如下所示。

package com.bjpowernode.hibernate;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtils {
	
	private static SessionFactory factory;

	//static只初始化一次.
	static
	{
		try{
		//默认读取的是hibernate.cfg.xml 文件.
				Configuration cfg = new Configuration().configure();
				
				//建立SessionFactory.
				factory = cfg.buildSessionFactory();
	
		}catch(Exception e )
		{
			e.printStackTrace();
		}
	}
	
	public static Session getSession()
	{
		//打开session.
		return factory.openSession();
	}
	
	//关闭session.
	public static void closeSession(Session session)
	{
		//判断是否为空.
		//判断是否是打开状态再进行关闭.
		
		if(session!=null)
		{
			if(session.isOpen())
			{
				session.close();
			}
		}
	}
	
	//返回工厂类.
	public static SessionFactory getSessionFactory()
	{
		return factory;
	}
}
	

Hibernate.cfg.xml代码如下所示。



  
	
    
    
     com.
     mysql.jdbc.Driver
     
    
     jdbc:mysql://localhost:3306/Hibernate_session
     
    
     root
     
    
     root
     
    
     org.hibernate.dialect.MySQLDialect
     
    
     true
     
     
   

  

上一篇,我们把对表添加的操作放到普通的java类中,在这个类的main()方法中执行,如果我们再对表进行其他的操作呢?那是不是还要建立新的java类,多个方法就不容易测试了。我们使用测试工具类JUnit来做测试,来测试增删改查。首先建立源目录,在test包中放测试程序。

我们建立我们的测试程序SessionTest.java,继承TestCase类,这样我们在SessionTest.java类中测试数据库中的某个方法,方法名的规范要以test开头。我们向User表中添加一条记录如下代码所示。

package com.bjpowernode.hibernate;

import java.util.Date;

import junit.framework.TestCase;

import org.hibernate.Session;
import org.hibernate.Transaction;

public class SessionTest extends TestCase {
	
	//测试方法以test开头.
	public void testSave1()
	{
		Session session = null;
		Transaction tx = null;
		try
		{
			//取得session.
			session = HibernateUtils.getSession();
			//自己开启事务. 返回 transient的一个实例.
			 tx = session.beginTransaction();
			
			//传入值.变为Transient状态.
			User user = new User();
			user.setName("张三");
			user.setPassword("123");
			user.setCreateTime(new Date());
			user.setExpireTime(new Date());