我对使用休眠多线程Java应用程序的工作。我们得到一个org.hibernate.StaleObjectStateException
因为我们有到位乐观锁定和某些实体(我们称之为Pojo
)从许多应用模块,它可以和已经在竞争条件(我没有设计的应用程序)相撞更新。有问题的代码块看起来是这样的:Hibernate会话没有刷新数据后,初始提交失败
Transaction txn = null;
HibernateException ex = null
for(int retryAttempt = 0; retryAttempt < 5; retryAttempt++) {
try {
txn = hibnSessn.beginTransaction();
int pojoID = pojo.getID();
pojo = hibnSessn.get(Pojo.class, pojoID);
pojo.setSomeVar("xyz");
txn.commit();
ex = null;
} catch(HibernateException e) {
if (txn != null)
{
txn.rollback();
}
ex = e;
// Gonna keep retrying
continue;
}
break;
}
而且Pojo.hbm.xml
开始是这样的:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.myproject.Pojo" table="pojo">
<id name="id" column="id" type="int">
<generator class="identity"/>
</id>
<!-- this is used to enforce optimistic locking -->
<version name="dbVersion" column="db_version"/>
...
这段代码在上面放重试循环的原作者正是因为有其他模块也更新Pojo
如果初始提交失败,由于竞争条件下,我们进入另外的尝试,希望能在一个干净,unconflicted交易成功。我不喜欢这种模式,但必须暂时与它合作。
我已经能够仪打破在行pojo.setSomeVar("xyz");
,从另一个线程/法和程序,从而未能提交并进入捕,由于乐观锁定更新数据库中的竞争条件,回滚和进入重试循环的下一次迭代。
问题是,在第二次迭代中,行pojo = hibnSessn.get(Pojo.class, pojoID);
不刷新pojo
与来自数据库的新数据,但从会话中拉出陈旧的对象,击败重试的目的。
另一个有趣的事情是,hibnSessn.get(...)
不会真正去到DB(正常情况下),因为当我提交失败之前hibnSessn.get
前更改数据从另一个线程/法在第一次迭代,对象也得到刷新。在提交失败并且事务回滚之后,它只会失败。
我寻找各种方法来强制Hibernate进入数据库,并刷新该对象在经过最初提交失败。
更新:我试着evict/refresh
在赶上刷新对象,但也导致StaleObjectStateException
。
有关使用查询,而不是刷新什么?类似于“来自Pojo的id =?”这只是一个尝试,基本上它们不应该有所不同。 –