zoukankan      html  css  js  c++  java
  • Hibernate的事务处理机制和flush方法的用法

    关于在使用hibernate在提交事务时常遇到的异常:

           an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
    net.sf.hibernate.AssertionFailure: possible nonthreadsafe access to session

    其实这个异常一般都是和我们在操作session flush方法和提交事务过程中会抛出的,下面就具体结合session的事务和声明周期来具体分析下,为什么会有这样的异常;

    首先来看下,session的生命周期

    Hibernatejava对象的三种状态:

    1、临时状态(transient):用new语句创建,还没有被持久化,不处于Session的缓存中。 

    2、持久化状态(persistent):已使用save()或者saveOrUpdate()方法,处于Session的缓存中和数据库表中,生成了自己的Oid标识。 

    3、游离状态(detached):被持久化,已使用evict(Object),session.close()或者使用clear()清除缓存,不再处于Session的缓存中或不存在数据库表中,但是依然是存在自己的OId标识。 

    对象的状态转换

                                                            

    从上面的图中我们可以很清楚的明白一个java对象在session中三种状态的转换,

    然后在来看看session缓存在什么时候会被清除:

    1.当应用程序调用org.hibernate.Transaction的commit()方法的时候,commit()方法先清理缓存,然后再向数据库提交事务。 

    2.当应用程序显式调用Session的flush()方法的时候,其实这个方法我们几乎很少用到,因为我们一般都是在完成一个事务才去清理缓存,提交数据更改,这样我们直接提交事务就可以。

    clear()evict(Object)的区别:

    从参数就可以看出,clear()是会清除整个session中的缓存,evict(Object)是将一个对象从session缓存中清除;

    其实在session持久化操作和数据库中之间还有一层对象缓冲区(entityEntries

     

    Commit():此方法在执行后会更新对象在对象缓存区中的existsInDatabase=true;

    Flush():会按save,update,delete顺序执行,把缓存中的数据flush入数据库中,并清空缓存区;

    下面几个例子可以充分说明我们异常抛出的情况:

    SessionFactory sf = new Configuration().configure().buildSessionFactory() ;
    Session s = sf.openSession();
    Person person = new Person();

    Transaction tran = s.beginTransaction(); (1)
    s.save(person); (2)(此处同样可以为update delete)
    s.evict(person); (3)
    tran.commit(); (4)
    s.close();(5)

    看上面的代码,再参照下我们的示例图和commit()方法,就可以很明显的发现代码问题的所在,在第四步evict()方法将cat对象从对象缓存区清除,当我们执行commit()方法后,更新对象在缓存区中状态的时候,由于已被清除,就会出现上述断言的异常;

    Person person1 = new Person ();
    person1.setName(“tom”);
    s.save(person1);

    person1.setName(“mary”);
    s.update(person1);

    Person person2 = new Person ();
    person2.setName(“tom”);
    s.save(person2);

    s.flush();

    其实在这里我们看这个代码的时候感觉是没问题 ,在这里我们可以参考下刚提到的flush()方法,此方法会按save,update,delete的顺序进行提交事务,所以在这里会抛出主键冲突的异常,解决的办法是在update()操作后面也加入flush();

    总的来说,由于flush()的特殊处理机制,虽然不建议使用此方法,但是在一些复杂的事务处理过程中,加入此方法虽然会破坏事务的一个提交的完整性,但是可以规避一些不可预见的异常情况!

  • 相关阅读:
    在Vue脚手架里面使用font-awsome
    在webstorm上使用git
    smartGit继续使用的方法
    工作笔记
    “老司机”传授给“小白”的职业经验
    兼容性问题(目前遇到的)
    web前端页面项目经验总结
    jquery中隐藏div的几种方法
    懒加载和预加载
    JS 中的事件绑定、事件监听、事件委托
  • 原文地址:https://www.cnblogs.com/wangkai1990/p/5704529.html
Copyright © 2011-2022 走看看