有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案

  1. # 1 楼答案

    我设法解决了我的问题。。我会等着接受它,以防其他人发布更好、更多的东西<值得赏金

    基本上,通过将FlushMode更改为手动,并在整个过程中手动刷新,我可以更早地捕获StaleObjectException,这会更快地退出代码。我仍然有部分回滚记录的人工制品。。但是,该方法按计划每2分钟运行一次,因此在第二次运行期间,它会修复所有问题

    我将EJB更改为具有以下内容:

    public void cutoffOrders(  ) throws Exception {
      Transaction tx = null;
      try {
          tx = getSession().beginTransaction();
          getSession().setFlushMode(FlushMode.MANUAL);
          getImpl().cutOffFoos(fooTime);
          getSession().flush();
          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 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 ...
                   sess.flush();
                   if( ... ) {
                       ... Code that makes new Bar object ...
                       foo.getBarList().add(bar2);
                   }
              }
              sess.flush();
              sess.update( foo );
          }
      }
    }