Hibernate基于配置文件(4)evict()与merge()的使用

Hibernate基于配置文件(四)evict()与merge()的使用

 

evict()与merge()都用于解决:

内存中存在2个id相同的对象,session发现对象不唯一而抛出异常。

 

package org.leadfar.hibernate.model;

import java.util.Date;

import junit.framework.TestCase;

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

public class UserTest03 extends TestCase {
	
	
	public void testUser_01() throws Exception {
		//默认读取类路径根目录下的hibernate.cfg.xml配置文件
		Configuration cfg = new Configuration().configure();
		
		//创建SessionFactory
		SessionFactory sfactory = cfg.buildSessionFactory();
		
		//创建Hibernate Session
		Session session = sfactory.openSession();
		
		//创建实体对象
		User user = new User();//此时User对象处于Transient(瞬时)状态
		user.setName("张三");
		user.setAge(20);
		user.setSex(false);
		user.setBirthday(new Date());
		user.setMoney(99999.99);
		user.setId(109);
		
		try {
			//开启事务
			session.beginTransaction();
			
			User dbUser = (User)session.get(User.class, 109);
			Date oldbirthday = dbUser.getBirthday();
			
			//session.update(user):发生异常。
			//具有相同标识符的不同对象与同一个session相关联,引发异常NonUniqueObjectException
			//org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [org.leadfar.hibernate.model.User#109]
			
			session.update(user);//update离线对象---当前session绑定的对象是dbUser,但是更新的是user对象(内存中存在两个对象与数据库中同一条记录(id=109)相关联)
			
			user.setName("手机");
			user.setBirthday(oldbirthday);
			
			
			//提交事务
			session.getTransaction().commit();
			
		} catch(Exception e) {
			e.printStackTrace();
			//出现异常,回滚事务
			session.getTransaction().rollback();
		} finally {
			//关闭session
			session.close();//session关闭之后,user对象处于离线Detached状态
		}
	}
	
	public void testUser_02() throws Exception {
		//默认读取类路径根目录下的hibernate.cfg.xml配置文件
		Configuration cfg = new Configuration().configure();
		
		//创建SessionFactory
		SessionFactory sfactory = cfg.buildSessionFactory();
		
		//创建Hibernate Session
		Session session = sfactory.openSession();
		
		//创建实体对象
		User user = new User();//此时User对象处于Transient(瞬时)状态
		user.setName("张三");
		user.setAge(20);
		user.setSex(false);
		user.setMoney(99999.99);
		user.setId(109);
		
		try {
			//开启事务
			session.beginTransaction();
			
			User dbUser = (User)session.get(User.class, 109);
			Date oldbirthday = dbUser.getBirthday();//获取以前对象的birthday
			
			//切断与session的连接,释放session
			session.evict(dbUser);
			
			//update离线对象,与session进行关联
			session.update(user);
			
			user.setName("手机");
			user.setBirthday(oldbirthday);//设置以前对象的birthday到新的对象中(保证birthday不变)
			
			
			//提交事务
			session.getTransaction().commit();
			
		} catch(Exception e) {
			e.printStackTrace();
			//出现异常,回滚事务
			session.getTransaction().rollback();
		} finally {
			//关闭session
			session.close();//session关闭之后,user对象处于离线Detached状态
		}
	}
	
	//merge解决了两个对象关联一个session的问题
	public void testUser_merge() throws Exception {
		//默认读取类路径根目录下的hibernate.cfg.xml配置文件
		Configuration cfg = new Configuration().configure();
		
		//创建SessionFactory
		SessionFactory sfactory = cfg.buildSessionFactory();
		
		//创建Hibernate Session
		Session session = sfactory.openSession();
		
		//创建实体对象
		User user = new User();//此时User对象处于Transient(瞬时)状态
		user.setName("美女2号线");
		user.setAge(20);
		user.setSex(false);
		user.setMoney(88.99);
		user.setId(109);//带更新的记录主键为109
		
		try {
			//开启事务
			session.beginTransaction();
			
			//dbUser与session关联
			User dbUser = (User)session.get(User.class, 109);

			user.setBirthday(dbUser.getBirthday());//设置以前对象的birthday到新的对象中(保证birthday不变)
			
			//merge--不用evict(驱逐)其它对象释放session
			//相当于把user对象的值拷贝到dbUser持久化对象中
			//由于没有调用update方法,所以user对象是处于瞬时状态的!
			//session关联的对象是dbUser,而user对象只是一个瞬时状态的对象
			session.merge(user);

			//提交事务
			session.getTransaction().commit();
			
		} catch(Exception e) {
			e.printStackTrace();
			//出现异常,回滚事务
			session.getTransaction().rollback();
		} finally {
			//关闭session
			session.close();//session关闭之后,user对象处于离线Detached状态
		}
	}
}