Hibernate的事务处理机制和flush方法的用法

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

       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的生命周期session

Hibernatejava对象的三种状态:ui

一、临时状态(transient):用new语句建立,尚未被持久化,不处于Session的缓存中。 this

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

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

对象的状态转换blog

                                                        

从上面的图中咱们能够很清楚的明白一个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()的特殊处理机制,虽然不建议使用此方法,可是在一些复杂的事务处理过程当中,加入此方法虽然会破坏事务的一个提交的完整性,可是能够规避一些不可预见的异常状况!

相关文章
相关标签/搜索