我们都知道,Java对象的生命周期,是从通过new语句创建开始,到不再被任何引用变量引用结束,结束后它占

用的内存将被JVM垃圾回收机制收回。在Hibernate持久化对象可以划分为三种状态,瞬时对象(Transient

 Objects)、持久化对象(Persistent Objects)和离线对象(Detached Objects也叫做脱管对象)。

       瞬时对象(Transient Objects)

       使用new操作符初始化的对象不是立刻就持久的。它们的状态是瞬时的,也就是说它们没有任何跟数据库表相关

联的行为,只要应用不再引用这些对象(不再被任何其它对象所引用),它们的状态将会丢失,并由垃圾回收机制回

收。 

       持久化对象(Persist Objects)

       持久实例是任何具有数据库标识的实例。它有持久化管理器Session统一管理,持久实例是在事务中进行操作的

——它们的状态在事务结束时同数据库进行同步。当事务提交时,通过执行SQL的INSERT、UPDATE和DELETE语句

把内存中的状态同步到数据库中。

       离线对象(Detached Objects)

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

Hibernate管理。

       持久化对象的三状态解析:

瞬时状态

       瞬时状态(Transient),也叫临时状态。处于这种状态的对象具备的特征如下:不在Session的缓存中,不与任何

的Session实例相关联;在数据库中没有与之相对应的记录。

       由Java的new命令开辟内存空间的Java对象也就是普通的Java对象,如果没有变量引用它它将会被JVM收回。临

时对象在内存中是孤立存在的,它的意义是携带信息载体,不和数据库中的数据由任何的关联。通过Session的save()

方法和saveOrUpdate()方法可以把一个临时对象和数据库相关联,并把临时对象携带的信息通过配置文件所做的映

射插入数据库中,这个临时对象就成为持久化对象。


持久状态

       持久状态(Persistent),处于这种状态的对象具备的特征如下:在Session的缓存中,与Session实例相关联;在数

据库中存在与之相对应的记录。

       持久化对象在数据库中有相应的记录,持久化对象可以是刚被保存的,或者刚被加载的,但都是在相关联的

session声明周期中保存这个状态。如果是直接数据库查询所返回的数据对象,则这些对象和数据库中的字段相关联,

具有相同的id,它们马上变成持久化对象。如果一个临时对象被持久化对象引用,也立马变为持久化对象。

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

何的联系。

       持久化对象总是与Session和Transaction关联在一起,在一个session中,对持久化对象的操作不会立即写到数据

库,只有当Transaction(事务)结束时,才真正的对数据库更新,从而完成持久化对象和数据库的同步。在同步之

前的持久化对象成为脏对象。

       当一个session执行close()、clear()、或evict()之后,持久化对象就变为离线对象,这时对象的id虽然拥有数据库

的识别值,但已经不在Hibernate持久层的管理下,他和临时对象基本上一样的,只不过比临时对象多了数据库标识

id。没有任何变量引用时,JVM将其回收。

       

脱管状态

        脱管状态(Detached),也叫游离状态。处于这种状态的对象具备的特征如下:不在Session的缓存中,不与任何

的Session实例相关联;在数据库中存在与之相对应的记录。(前提条件是没有其他Session实例删除该条记录)。

       Session关闭之后,与此Session关联的持久化对象就变成为脱管对象,可以继续对这个对象进行修改,如果脱管

对象被重新关联到某个新的Session上,会在此转成持久对象。

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


       持久化对象的三种状态是可以相互转化的,具体转换过程如图所示:

       

JAVA持久类 java持久化对象_框架


        实例

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

       我们新建的项目实例的HIbernate核心配置文件:


<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory>
	    <!-- 连接数据库参数 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">root</property>
		
		<!-- MySQL数据库方言 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		
		<!-- 输出SQL语句到控制台 -->
		<property name="hibernate.show_sql">true</property>
		<property name="hibernate.format_sql">true</property>
		
		<!-- 自动将hbm映射文件生成ddl语句 -->
		<property name="hibernate.hbm2ddl.auto">update</property>
		
		<!-- 使用getCurrentSession获取session -->
		<property name="hibernate.current_session_context_class">thread</property>
		
		<!-- 对象关系映射文件地址 -->
		<mapping resource="com/demo/domain/User.hbm.xml"/>
		<!--  
		<mapping resource="com/demo/domain/User1.hbm.xml"/>
		<mapping resource="com/demo/domain/User2.hbm.xml"/>
		<mapping resource="com/demo/domain/User3.hbm.xml"/>
		-->
	</session-factory>
</hibernate-configuration>




       实体类User:


package com.demo.domain;

import java.util.Date;

/**
 * User实体类
 * @author Administrator
 * @date 2016年12月4日
 */
public class User {

	private String id;
	private String name;
	private String password;
	private Date createTime;
	private Date expireTime;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}

	public Date getExpireTime() {
		return expireTime;
	}

	public void setExpireTime(Date expireTime) {
		this.expireTime = expireTime;
	}

	@Override
	public String toString() {
		return "User [id=" + id + ", name=" + name + ", password=" + password + ", createTime=" + createTime
				+ ", expireTime=" + expireTime + "]";
	}
	
}

       对象关系映射文件:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<!-- 对象关系映射配置文件 -->
<hibernate-mapping>
    <!-- 通过User实体类映射出user表 -->
	<class name="com.demo.domain.User" table="user">
	    <!-- 映射主键 -->
		<id name="id">
		    <!-- 主键生成策略机制 -->
			<generator class="uuid"/>
		</id>
		<!-- 映射普通字段 -->
		<property name="name"/>
		<property name="password"/>
		<property name="createTime"/>
		<property name="expireTime"/>
	</class>
</hibernate-mapping>

       当我们建立Session都要实例化SessionFactory,所以我们把重复的代码进行封装,并且session是单线程的。我

们把对session的管理,打开session,关闭session等封装到工具类HibernateUtils中,代码如下:


package com.demo.domain;

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

/**
 * 得到会话工厂的工具类
 * @author Administrator
 * @date 2016年12月8日
 */
public class HibernateUtils {

	//静态变量
	private static SessionFactory factory;
	
	//静态代码块,只会装载一次
	static {
		try {
			//读取hibernate.cfg.xml文件
			Configuration cfg = new Configuration().configure();
			
			//建立SessionFactory
			factory = cfg.buildSessionFactory();
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
	
	//通过静态方法得到session
	public static Session getSession() {
		return factory.openSession();
	} 
	
	//通过静态方法关闭session
	public static void closeSession(Session session) {
		if (session != null) {
			if (session.isOpen()) {
				session.close();
			}
		}
	}
	
	//通过静态方法得到会话工厂
	public static SessionFactory getSessionFactory() {
		return factory;
	}
	
}

       测试类:


package com.demo.test;

import java.util.Date;

import junit.framework.TestCase;

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

import com.demo.domain.HibernateUtils;
import com.demo.domain.User;

public class SessionTest extends TestCase {

	public void testSave1() {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtils.getSession();
			tx = session.beginTransaction();
			
			//user对象刚创建时为Transient状态
			User user = new User();
			user.setName("张三");
			user.setPassword("123456");
			user.setCreateTime(new Date());
			user.setExpireTime(new Date());
			
			/*
			 * 进行保存,执行save则对session进行管理了. 处于Persistent状态
			 * Persistent状态的对象,当对象的属性发生改变的时候
			 * hibernate在清理缓存(脏数据检查)的时候,会和数据库同步
			 */
			session.save(user);//insert语句
			
			//更新user对象的name值李四
			user.setName("李四");//update语句
			
			//可以显示的调用update方法,因为此时为持久状态,调用update没有什么意义
			//session.update(user);
			
			//提交事务
			tx.commit();
			
		}catch(Exception e) {
			e.printStackTrace();
			if (tx != null) {
				//回滚事务
				tx.rollback();
			}
		}finally {
			//关闭session.当关闭session时处于Detached状态.
			HibernateUtils.closeSession(session);
		}
	}
	
	public void testSave2() {
		Session session = null;
		Transaction tx = null;
		User user = null;
		try {
			session = HibernateUtils.getSession();
			tx = session.beginTransaction();
			
			//Transient状态
			user = new User();
			user.setName("陈曦");
			user.setPassword("123456");
			user.setCreateTime(new Date());
			user.setExpireTime(new Date());
			
			/*
			 * 进行保存,执行save则对session进行管理了. 处于Persistent状态
			 * Persistent状态的对象,当对象的属性发生改变的时候
			 * hibernate在清理缓存(脏数据检查)的时候,会和数据库同步
			 */
			session.save(user);
			
			//更新
			user.setName("陈艾");
			
			tx.commit();
			
		}catch(Exception e) {
			e.printStackTrace();
			if (tx != null) {
				tx.rollback();
			}
		}finally {
			//Detached状态
			HibernateUtils.closeSession(session);
		}
		
		
		//已经不能用以前的session了
		user.setName("陈成");
		
		try {
			//得到新的session
			session = HibernateUtils.getSession();
			session.beginTransaction();
			
			//将Detached状态的对象重新纳入session管理
			//此时将变为Persistent状态的对象
			//Persistent状态的对象,在清理缓存是会和数据库同步
			session.update(user);
			
			session.getTransaction().commit();
		}catch(Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}	
	
}

       testSave1()方法

       首先是建立对象与表的会话session,开启事务session.beginTransaction(),实例化User对象,当我们User user

 = new User()的时候,当我们new一个对象的时候数据库是没有的,所以是Transient对象(临时对象),然后给

user赋值,设置名称和密码以及其他属性。 为对象的所有属性赋值完毕,接下来保存到会话session中,拿到session

执行save(user)方法。 当我们执行session的save()方法时,这个对象就被session管理了,session中有个

map,会把对象放到map中,此时的对象我们就成为Persistent状态(持久状态)。接下来我们又把user中的name

属性设置为“李四”,之后提交事务。我们先再会话中存储的“张三”,之后改为“李四”。try catch来扑捉异常,

当执行完毕,关闭session后,对象处于detached状态(离线状态)。

       控制台输出:

       

JAVA持久类 java持久化对象_ORM框架_02

       数据库显示:

       

JAVA持久类 java持久化对象_Hibernate_03

       testSave2()方法:

       只是解释后面第二次更新,也就是把"陈艾"改为"陈成",取得Detached状态的user对象,改变这个对象的name

值,user.setName("陈成");之后我们再new一个新的session,通过session开启事务,之后更新操作,

session.update(user),也就是把离线的对象(或脱管对象)再纳入session管理,这样就会和数据库同步,因为

session.update()就把user对象纳入session管理,user对象由离线状态变为Persistent状态。


       控制台输出:

   

JAVA持久类 java持久化对象_JAVA持久类_04

       数据库显示:

       

JAVA持久类 java持久化对象_框架_05