Hibernate学习笔记Session.evict(user)方法

@[TOC]Hibernate学习笔记Session.evict(user)方法

Hibernate学习笔记Session.evict(user)方法

首先我们要明白Session.flush(user)方法,这个方法主要做了三件事:

  1. 根据session缓存中的临时集合insertion中的state区中的数据(user对象),发送sql语句。
  2. 清空临时集合中的数据。
  3. 向session中的缓存map中的existsInDatebase状态设置为为true,表示数据库中已经有了这个数据。

接着来看session.evict(user);这句话表示将user对象从Session缓存中逐出,即从Session中的EntityEntries属性中逐出。这句话的作用就是清理session缓存,以防数据量过多,造成缓存的崩溃。

接着来看下面代码:

第一个例子:

/**
	 * 测试uuid主键生成策略
	 */
	public void testSave1() {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtils.getSession();//通过session工厂获取session对象
			tx = session.beginTransaction();//开启事务

			User1 user = new User1();
			user.setName("李四");
			user.setPassword("123");
			user.setCreateTime(new Date());
			user.setExpireTime(new Date());
			
			session.save(user);
			//这里设置user的主键为userId,主键生成策略为uuid,所以调用完成save后,只是将user纳入到了session的管理,
			//不会发出insert语句,但是id已经生成,session(缓存)中existsInDatebase状态为false(数据库中并不存在)
			
			session.flush();
			//调用flush,hibernate会清理缓存,1,根据临时集合执行sql
			//如果数据库的隔离级别设置为为提交读,那么我们可以看到flush过的数据
			//2,清空临时集合中的数据
			//3,并且session中existsInDatebase状态为true(表示数据库中已经存在)
					
			//提交事务
			//默认情况下commit操作会先执行flush清理缓存,所以不用显示的调用flush
			//commit后数据是无法回滚的
			tx.commit();
		}catch(Exception e) {
			e.printStackTrace();
			tx.rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}


在native主键生成策略中,由于主键生成策略是uuid,所以在save的时候并不会发送sql语句进行保存,所以这个时候,如果使用session.evict(user);清理缓存中的user对象,那么无法成功commit,因为hiberbate清理完临时集合之后,需要将existsInDatebase状态为true,这个时候由于evict已经将user对象从session缓存中逐出,所以hibernate找不到相关数据,所以提交失败。

/**
	 * 测试uuid主键生成策略中的session.evict(user)。
	 */
	public void testSave3() {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtils.getSession();
			tx = session.beginTransaction();

			User1 user = new User1();
			user.setName("王五");
			user.setPassword("123");
			user.setCreateTime(new Date());
			user.setExpireTime(new Date());
			
			//因为user的主键生成策略采用的是uuid,所以调用完成save后,只是将user纳入到了session的管理
			//不会发出insert语句,但是id已经生成,session中existsInDatebase状态为false
			session.save(user);
			
			//将user对象从session(缓存)中逐出,即session的EntityEntries属性中逐出
			session.evict(user);//目的是清除map中的缓存中的user对象。
			
			//无法成功提交,因为hibernate在清理缓存时,在session的临时insertions集合中取出user对象进行insert操作后
			//需要更新entityEntries属性中的existsInDatabase为true,而我们采用evict已经将user从session的entityEntries
			//中逐出了,所以找不到相关数据,无法更新,抛出异常   
			tx.commit();
		}catch(Exception e) {
			e.printStackTrace();
			tx.rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}

解决方法:在session.exict(user);语句之前使用session.flush();,这样子hibernate会清理缓存,会将user对象保存到数据库中,将session中的insertions中的user对象清除,并且设置session中existsInDatebase的状态为true,那么在commit的时候,会根据session缓存中insertion中的state中的数据发送sql语句,由于之前已经将user对象从缓存中逐出,所以这个时候找不到user对象,于是就不会发送sql语句也不会更新existsInDatebase的状态,也不会出异常了。
看代码:

/**
	 * 测试uuid主键生成策略
	 */
	public void testSave4() {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtils.getSession();
			tx = session.beginTransaction();

			User1 user = new User1();
			user.setName("王五");
			user.setPassword("123");
			user.setCreateTime(new Date());
			user.setExpireTime(new Date());
			
			//因为user的主键生成策略采用的是uuid,所以调用完成save后,只是将user纳入到了session的管理
			//不会发出insert语句,但是id已经生成,session中existsInDatebase状态为false
			session.save(user);
			
			//flush后hibernate会清理缓存,会将user对象保存到数据库中,将session中的insertions中的user对象
			//清除,并且设置session中existsInDatebase的状态为true
			session.flush();
			
			//将user对象从session中逐出,即session的EntityEntries属性中逐出
			session.evict(user);
			
			//可以成功提交,因为hibernate在清理缓存时,在session的insertions集合中无法找到user对象
			//所以就不会发出insert语句,也不会更新session中的existsInDatabase的状态
			tx.commit();
		}catch(Exception e) {
			e.printStackTrace();
			tx.rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}

使用native主键生成策略,毫无疑问,不用在session.evict之前显示调用flush方法,也是行的通的。因为他在save的时候就已经发送了sql语句了,然后commit的时候,找不到user对象之后,不会发送sql也是无所谓的了,因为之前已经发送过了。
看代码:

/**
	 * 测试native主键生成策略
	 */
	public void testSave5() {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtils.getSession();
			tx = session.beginTransaction();

			User2 user = new User2();
			user.setName("张三11");
			user.setPassword("123");
			user.setCreateTime(new Date());
			user.setExpireTime(new Date());
			
			//因为user的主键生成策略为native,所以调用session.save后,将执行insert语句,返回有数据库生成的id
			//纳入了session的管理,修改了session中existsInDatebase状态为true
			//如果数据库的隔离级别设置为非提交读,那么我们可以看到save过的数据
			session.save(user);
			
			//将user对象从session中逐出,即session的EntityEntries属性中逐出
			session.evict(user);
			
			//可以成功提交,因为hibernate在清理缓存时,在session的insertions集合中无法找到user对象
			//所以就不会发出insert语句,也不会更新session中的existsInDatabase的状态
			tx.commit();
		}catch(Exception e) {
			e.printStackTrace();
			tx.rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}

主键生成策略为designed的时候,分析思略和之前的一样,
看代码:

/**
	 * 测试assigned主键生成策略
	 * 
	 */
	public void testSave7() {
		Session session = null;
		Transaction tx = null;
		try {
			session = HibernateUtils.getSession();
			tx = session.beginTransaction();

			User3 user = new User3();
			user.setId("003");
			user.setName("张三");
			
			session.save(user);
			
			user.setName("王五");
			session.update(user);
			
			session.flush();
			
			User3 user3 = new User3();
			user3.setId("004");
			user3.setName("李四");
			session.save(user3);
			
			//Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)
			//Hibernate: update t_user3 set name=?, password=?, create_time=?, expire_time=? where user_id=?
			//Hibernate: insert into t_user3 (name, password, create_time, expire_time, user_id) values (?, ?, ?, ?, ?)
			//因为我们在session.udpate(user)后执行了flush,所以在清理缓存时执行flush前的sql不会生成
			//sql会按照我们的意愿执行
			tx.commit();
		}catch(Exception e) {
			e.printStackTrace();
			tx.rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}

我们的对手不是天才,而是脚踏实地的人。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hibernate中,Session是一个重要的接口,它代表了应用程序与数据库之间的一次会话。Session对象提供了对数据库的CRUD操作,包括添加、查询、更新、删除等操作。 Session的作用主要有以下几点: 1. 提供CRUD操作:Session对象提供了对数据库的CRUD操作,可以通过Session对象进行数据的添加、查询、更新、删除等操作。 2. 数据库事务管理:Session对象提供了事务管理的功能,可以通过Session.beginTransaction()方法开始事务,Session.getTransaction().commit()方法提交事务,Session.getTransaction().rollback()方法回滚事务。 3. 缓存管理:Hibernate提供了一级缓存和二级缓存,Session对象可以管理一级缓存,提高查询性能。 4. 对象状态管理:Session对象可以管理Java对象的状态,包括脱管状态、持久状态和游离状态等,可以通过Session.save()方法将对象从脱管状态转换为持久状态,通过Session.evict()方法将对象从持久状态转换为游离状态等。 5. 延迟加载:Hibernate支持延迟加载,可以通过Session.get()方法Session.load()方法进行延迟加载,减少数据库的访问次数。 总之,SessionHibernate框架中的一个重要接口,它提供了对数据库的CRUD操作、事务管理、缓存管理、对象状态管理和延迟加载等功能。Session的使用可以方便地进行数据库操作,提高了开发效率和代码可维护性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值