java JPA/Hibernate不希望的部分回滚和会话处理
我使用一个无状态EJB类来更新数据库中的持久性实体。EJB中的方法调用完成工作的实现类。我认为导致这个问题的原因是一个名为Foo
的实体与一个实体Bar
有一个单一的关系。事情完成了,会话被更新为Foo
,它“级联”到Bar
。当StaleObjectStateException
发生时,事务没有被完全回滚,这会由于明显的原因导致错误
EJB:
private Session getSession() throws BusinessException {
if( this.sess == null ) {
ServiceLocator locator = new ServiceLocator();
SessionFactory sf = locator.getHibernateSessionFactory();
this.sess = sf.openSession();
}
return this.sess;
}
private ProductionOrderImpl getImpl() throws BusinessException {
if( this.impl == null ) {
this.impl = new ProductionOrderImpl( getSession() );
}
return this.impl;
}
public void cutoffOrders( ) throws Exception {
Transaction tx = null;
try {
tx = getSession().beginTransaction();
getImpl().cutOffFoos(fooTime);
tx.commit();
} catch (StaleObjectStateException e1){
if (tx != null) tx.rollback();
logger.error( "Failed to cutoff order : " + e1 );
throw new Exception( LocaleMgr.getMessage());
}
finally {
// reset implementation object, close session,
// and reset session object
impl = null;
sess.close();
sess = null;
}
}
实施:
public ProductionOrderImpl(Session sess) {
this.sess = sess;
}
public void cutoffFoos( Timestamp fooTime) throws Exception {
... Code that gets fooList ...
if( fooList != null ) {
for( Foo foo: fooList ) {
for( Bar bar : foo.getBarList() ) {
... Code that does things with existing Barlist ...
if( ... ) {
... Code that makes new Bar object ...
foo.getBarList().add(bar2);
}
}
sess.update( foo );
}
}
}
相关食品代码:
@OneToMany(cascade=CascadeType.ALL, mappedBy="foo")
@OrderBy("startTime DESC")
Set<Bar> barList;
因此,基本上,当事务尝试回滚时,已更改的条形图部分会回滚,但新的条形图(代码中的bar2)记录会保留
任何指导都将不胜感激。就像我说的,我相信这里的错误与sess.update(foo)
有关;可能与autocommit
有关,但默认情况下它应该是关闭的
我相信正在发生的事情,就是这次会议。更新(foo)反过来创建两个独立的事务。具体来说,Foo
被更新(SQL更新),但Bar
被保存(SQL插入)。因为事务上下文只会真正看到SQL更新,所以它只会反转。我们得进一步调查
我尝试过将Session.FlushMode
改为COMMIT
,但似乎仍然无法解决问题。然而,它确实部分解决了这个问题。。它将正确回滚条目,但导致StaleObjectStateException的特定条目除外。这个条目实际上是从数据库中删除的
# 1 楼答案
我设法解决了我的问题。。我会等着接受它,以防其他人发布更好、更多的东西<值得赏金
基本上,通过将
FlushMode
更改为手动,并在整个过程中手动刷新,我可以更早地捕获StaleObjectException
,这会更快地退出代码。我仍然有部分回滚记录的人工制品。。但是,该方法按计划每2分钟运行一次,因此在第二次运行期间,它会修复所有问题我将EJB更改为具有以下内容:
然后,实现代码将包含以下内容: