自动调用和数据库回滚

时间:2013-09-05 14:16:31

标签: java database transactions

我有一些代码从表中读取要发送的邮件列表并发送它们。

按顺序进行的操作是:

  1. 设置表格中发送的标志
  2. 自动拨打电话
  3. 提交
  4. 在自动呼叫之前进行更新的原因是,如果出现故障,我可以回滚而不进行自动呼叫。但如果是另一种方式,我最终会在可能的情况下进行调用而无法更新记录(如果数据库出现问题)。

    public class MyDao {
    
        public void doSomethingOnDb() {
            try {
                // operation 1 : execute an update (setting the letter as sent)
                // operation 2 : make automatic call    
                // operation 3 : commit
            }
            catch(Exception e) {
                // Rollback
            }
        }   
    }
    

    我在这里不喜欢的是我正在放置一个功能来在dao中进行自动调用,这不是dao应该做的事情。但是,如果我将逻辑分开,我无法确定表中的标志是否真实。我们可以进行调用并且无法将标志更新到db:

    public class MyDao {
    
        public void doSomethingOnDb() {
            try {
                // operation 1 : execute an update (setting the letter as sent)
                // operation 2 : commit
            }
            catch(Exception e) {
                // Rollback
            }
    
        }   
    }
    
    public void someOtherMethodSomewhere() {
        try { 
            new MyDao().doSomethingOnDb();
            // operation 3 : make the automatic call
        }
        catch(Exception e) {
        }
    }
    

    那么,你会怎么做?还有其他解决方案吗?

2 个答案:

答案 0 :(得分:0)

这是一个经典的多资源事务(distributed transaction)。我建议您阅读有关XA事务的信息,例如Two Phase Commit protocol

也许你正试图解决另一个问题?如果我理解正确,那么您可能只需要更改代码?例如。你可以从dao返回成功:

if(doSomethingOnDb()) 
{
   //make the automatic call
}

即。如果更改成功并提交,则dao调用返回true。

如果失败,你也可以从doSomethingOnDb抛出异常,在这种情况下

try { 
    new MyDao().doSomethingOnDb();
    // operation 3 : make the automatic call
}
catch(Exception e) {
}

跳过operation 3并进入catch区块。

或者只是将dao传递给要执行的函数:

public void doSomethingOnDb(Runnable precommit) {
    try {
        // operation 1 : execute an update (setting the letter as sent)
        precommit.run();    
        // operation 3 : commit
    }
    catch(Exception e) {
        // Rollback
    }
}   

...
myDao.doSomethingOnDb(new Runnable()
{
   void run()
   {
        // operation 3 : make the automatic call
   }
});

答案 1 :(得分:0)

难道你不能简单地将DAO操作分成子方法吗?类似的东西:

public class MyDao {
    public void executeAnUpdate() {...}
    public void commit() {...}
}

public class MyBusiness {
    public void run() {
        myDao.executeAnUpdate();
        // make the automatic call
        myDao.commit();
    }
}