在回滚过程中启动新事务

时间:2011-01-26 10:10:00

标签: java transactions jboss java-ee ejb-3.0

我正在使用Jboss5.1.x EJB3.0

我试图在回滚过程中打开新的Transaction以写入数据库。

我能做的唯一方法 t,是当我将事务包装在一个单独的线程中时,这对我来说似乎不对。 它可能会导致任何问题吗?这样做的意义是什么(用新线程换行), 它假设在没有它的情况下工作不是吗?

代码:

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
private void updateCurrentRetryInDB(final CounterCallData counterCall)
{
    Thread t = new Thread()
    {
        @Override
        public void run()
        {
            try
            {
                ECMSDao.insertErrorToLog(counterCall.getModemIp(), "Time out");
            } catch (SQLException e)
            {
                System.out.println("SQL Exception:" + e.getMessage());
                logger.error(TAG + ".updateCurrentRetryInDB, SQLException Error", e);
            }
        }
    };
    t.start();
}

谢谢, 射线。

2 个答案:

答案 0 :(得分:2)

我有与你相同的要求,在回滚过程中在数据库中写一些东西。

我所做的是创建一个新的有状态EJB,它具有@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)并调用存储在数据库中的save方法。

我没有创建新线程或任何东西,因为这应该由容器处理。

因此,在您的情况下,我认为ECMSDao应该是@Stateful ejb @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)而不是方法updateCurrentRetryInDB()

<强>更新

假设你有正常情况存储东西,并发生回滚。 在此示例中,我使用托管事务进行模拟。

public class Foo {

@PersistenceContext EntityManager em;

@Inject BarImpl bar; //can also use @EJB depending on your environment

public void fail() {
   try {
     //do some thing and throw exception to simulate rollback
      throw new RuntimeException("Exception occured, please rollback");
   } catch(Exception ex) {
     bar.save(ex.getMessage()); // <-- This will store the exception message in a new transaction whilst the other transaction is safely rolledback
     throw ex;
   }
}

@Scope(SESSION)
@Stateful
@TransactionManagement(TransactionManagementType.CONTAINER) //default
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class BarImpl implements Bar {

   @PersistenceContext EntityManager em;    
   @Destroy @Remove public void destroy(){}

    public void save(String msg) { 
      MyEntity m = new MyEntity(); 
      m.setMessage(msg); 
      em.persist(m);
    }

}

答案 1 :(得分:-1)

没有“回滚的中间”这样的东西,因为事务是原子的,因此它已被回滚或没有回滚。我建议使用jms进行日志记录。 另请注意,根据JSR 220:Enterprise JavaBeansTM,版本3.0:

“企业bean不得尝试管理线程。企业bean不得尝试 启动,停止,暂停或恢复一个线程,或改为“,所以至少你可能会影响可移植性。