我有一些代码从表中读取要发送的邮件列表并发送它们。
按顺序进行的操作是:
在自动呼叫之前进行更新的原因是,如果出现故障,我可以回滚而不进行自动呼叫。但如果是另一种方式,我最终会在可能的情况下进行调用而无法更新记录(如果数据库出现问题)。
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) {
}
}
那么,你会怎么做?还有其他解决方案吗?
答案 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();
}
}