Session的一些操作和注意点

Session.evict()

作用:从session缓存(EntityEntries属性)中逐出该对象.


但是与commit同时使用,会抛出异常   
            session = HibernateUtils.getSession();   
            tx = session.beginTransaction();   
       
            User1 user = new User1();   
            user.setName("李四");   
            user.setPassword("123");   
            user.setCreateTime(new Date());   
            user.setExpireTime(new Date());   
               
            //利用Hibernate将实体类对象保存到数据库中   
            //因为user主键生成策略采用的是uuid,所以调用完成save后,只是将user纳入session的管理   
            //不会发出insert语句,但是id已经生成,session中的existsInDatabase状态为false   
            session.save(user);   
                   
            session.evict(user);//从session缓存(EntityEntries属性)中逐出该对象   
        //无法成功提交,因为hibernate在清理缓存时,在session的临时集合(insertions)中取出user对象进行insert操作后需要更新entityEntries属性中的existsInDatabase为true,而我们采用evict已经将user从session中逐出了,所以找不到相关数据,无法更新,抛出异常。   
               
            tx.commit();   
  
解决在逐出session缓存中的对象不抛出异常的方法:   
在session.evict()之前进行显示的调用session.flush()方法就可以了。   
        //利用Hibernate将实体类对象保存到数据库中   
            //因为user主键生成策略采用的是uuid,所以调用完成save后,只是将user纳入session的管理   
            //不会发出insert语句,但是id已经生成,session中的existsInDatabase状态为false   
            session.save(user);   
                   
            //flush后hibernate会清理缓存,会将user对象保存到数据库中,将session中的insertions中的user对象清除,并且会设置session中的existsInDatabase状态为false   
            session.flush();   
               
            session.evict(user);//从session缓存(EntityEntries属性)中逐出该对象   
               
            //可以成功提交,因为hibernate在清理缓存时,在Session的insertions中集合中无法找到user对象所以不会发出insert语句,也不会更新session中existsInDatabase的状态。   

Session.clear()

作用:清空session缓存


Session.flush()

作用:将session的缓存中的数据与数据库同步

PS:执行sql语句,但是不会提交


当更新或者保存大批量数据的时候,可以每固定数量的时候,进行清理缓存,同时清除缓存:

for (int i = 0; i < 1000;i ++){

     if (i /20 == 0) {

        session.flush();
    
        session.clear();

     }

}

因为把大量的对象放到session缓存中会浪费大量的内容空间。


执行完session.flush()时,并不意味着数据就肯定持久化到数据库中的,因为事务控制着数据库,如果事务提交失败了,缓存中的数据还是照样会被回滚的。



这里是LZ看网上看到的一些session基础的资料。

Session里的对象有三种状态

       1、自由状态

       2、持久化状态

       3、游离状态


      自由状态:new出来的类,未与session绑定

     持久化状态:session的save,update,persist等操作之后的对象就会与session绑定,即 持久化

     游离状态: session的evict该对象,则成为了游离状态

----------------------------------------------------咯咯咯咯咯咯---------------------------------------------------------------------------------------

2014-04-26:

今天自己在做SQLQuery测试的时候,忘记提交事务了,然后就又学到了东西!

public class Test {
	public static void main(String[] args) throws IOException {
		SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
		Session session = sf.openSession();
		VO vo = new VO();
		vo.setName("那哈哈哈");
		session.beginTransaction();
		session.save(vo);
		System.out.println(vo.getId());
		
		session.getTransaction()
		session.close();
		sf.close();
		
	}
}

感觉自己一直没学好session


之前的我在想,这个打印出来的肯定是0;(默认:0)


但是打印出来的是12(数据库里已经有11个数据)


ps:之前保存了一个数据进数据库,但是又想知道自动生成的主键编号,然后就执行各种查询才得到(且高并发的时候还不一定能得到正确的)


ps:原来session早就已经帮我实现了。。。


但是这个方法,我没有提交事务。


我查看了一下数据库,里面还是11个数据,但是vo能实现主键递增且与数据库同步。


我有点明白session.flush()所说的与数据库同步的意思了。


以前一直以为flush了,就保存进数据库了。其实事务不提交,就不会保存进数据库。


第二个例子:

public class Test {
	public static void main(String[] args) throws IOException {
		SessionFactory sf = new AnnotationConfiguration().configure().buildSessionFactory();
		Session session = sf.openSession();
		session.beginTransaction();
		SQLQuery query = session.createSQLQuery("update vo set name = '喀喀' where id = 2");
		session.getTransaction().commit();
//		query.executeUpdate();
		session.close();
		sf.close();
	}
}

这里我用到了SQLQuery。但是我没有调用executeUpdate()方法


然后提交了事务。


数据库里的数据什么都没有改变


这个时候我在事务提交之后,再执行executeUpdate()方法


控制台打印出:

Hibernate: update vo set name = '喀喀' where id = 2


我本能的就觉得执行成功了。但是事实是数据库还是没有改变。


最后在事务未提交前执行就OK了。


学的时候,依样画葫芦就可以了,知道写begintransaction和commit之间就可以了。


但是一直是知其然不知其所以然。


今天算是弄懂了点。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值