Hibernate 中session.evict(obj):possible nonthreadsafe access to session

本文探讨了在使用Hibernate框架时遇到的session.evict()引发的错误,并详细解析了问题的原因及解决方案。通过调整代码逻辑,确保了session.flush()之前对象仍然存在于会话中,避免了可能的线程安全问题。

Hibernate 中session.evict(obj):possible nonthreadsafe access to session

 

使用Hibernate 中session.evict方法时,报了如题的错误,另外,还有如下的提示:
Hibernate: insert into TEST (version, NAME, CODE, ID) values (?, ?, ?, ?)
23:45:03,343 ERROR AssertionFailure:47 - an assertion failure occured (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session)
org.hibernate.AssertionFailure: possible nonthreadsafe access to session
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:83)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at netway.core.database.DataBase.SavaObjSet(DataBase.java:84)
at BatchTest.testdb(BatchTest.java:102)
at BatchTest.main(BatchTest.java:78)
org.hibernate.AssertionFailure: possible nonthreadsafe access to session
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:83)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:167)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at netway.core.database.DataBase.SavaObjSet(DataBase.java:84)
at BatchTest.testdb(BatchTest.java:102)
at BatchTest.main(BatchTest.java:78)


从提示中可以看出,是不安全的使用session,调用代码如下:
public boolean SavaObjSet(List<?> objset) throws HibernateException
{
try
{
this.startTransaction();
Iterator<?> it = objset.iterator();

// 数据量太大时,清除缓存(太大时,一般是插入操作,留作缓存没有太大意义)
boolean bMayClear = objset.size() > 1 ? true : false;

while (it.hasNext())
{
Object obj = it.next();
session.saveOrUpdate(obj);

if (bMayClear)
session.evict(obj);
}

session.flush();
this.commitTransaction();
}
catch (HibernateException eh)
{
this.rollbackTransaction();
throw eh;
}
return true;
}
在上面的代码中,为防止没有必要的数据加入到 session 中,凡是保存或更新过的数据,一律从 session 的缓存中清除。session.evict 的方法就是从 sessioin 中清除指定的对象。经过调试跟踪,问题出在session.flush()这儿,session.flush()就是让 hibernate 立即执行 sql 语句,但是并不提交,同时更新缓存,session.flush()出现问题,那就是在构造 sql 时,出了问题。如果是在执行sql 时出问题,错误提示是不相同的。向上推理,那就是 session.saveOrUpdate(obj) 的对象 obj 出了问题,导致hibernate 没有办法构造 sql, 可以肯定的是,session.saveOrUpdate(obj) 中的对象obj 是正确的,最后,问题定位在session.evict(obj),原来,在我们提交事务前,已将对象从session 中删除了,导致session.flush()没有对象去构造sql语句,注释后,测试,一切正常。
更改后代码如下:
public void saveOrUpdateObjSet(List<?> objset) throws HibernateException
{
this.startTransaction();
Iterator<?> it = objset.iterator();

while (it.hasNext())
{
Object obj = it.next();
session.saveOrUpdate(obj);
}
this.commitTransaction();

//清理缓存
if (objset.size() > 100)
{
it = objset.iterator();
while (it.hasNext())
{
session.evict(it.next());
}
}
}

如果使用 session.clear(),会将所有的缓存全部清除,这不是我们想要的,所以采用session.evict(it.next()).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值