10

我正在开发一个使用 Spring IoC和 JDBC 模板类的 Java 应用程序。我有一个 DAO 类,它有 4 个方法:m1() 到 m4()。m1 在表 t1 上执行多次插入和更新,在表 t2 上执行 m2,在 t3 上执行 m3 等。

DAO 方法使用如下:

while(true)
{
  //process & generate data

  dao.m1(data1);
  dao.m2(data2);
  dao.m3(data3);
  dao.m4(data4);

  //sleep
}

我希望 4 个连续方法调用下的 db 操作是原子的,要么所有 4 个表都成功更新,要么没有。因此,如果在 m3() 中执行操作时出现错误,我想回滚在 m2 和 m1 中执行的所有更改(更新和插入)。

那么 spring 是否允许您按照以下方式进行操作?

while (true)
{
  //process & generate data

  transaction = TransactionManager.createNewTransaction();

  transaction.start()

  try
  {
    dao.m1(data1);
    dao.m2(data2);
    dao.m3(data3);
    dao.m4(data4);
  }
  catch(DbUpdateException e)
  {
    transaction.rollBack();
  }

  transaction.end();

  // sleep

}

或者有更好的方法吗?

4

4 回答 4

15

是的,Spring 允许您以编程方式控制事务

就个人而言,我更喜欢使用注释的声明性事务,如下所示:

public void runBatchJob() {
  while (true) {
    // generate work
    doWork(unitOfWork);
  }
}

@Transactional
private void doWork(UnitOfWork work) {
  dao.m1(data1);
  dao.m2(data2);
  dao.m3(data3);
  dao.m4(data4);
}

定义DAO函数的地方:

@Transactional
public void m1(Data data) {
  ...
}

这需要在您的applicationContext.xml中:

<tx:annotation-driven/>

声明性事务可以声明为需要一个事务、需要一个新事务、支持事务等。当一个带有注释的块@Transactional抛出一个RuntimeException.

于 2009-06-21T13:41:31.717 回答
8

为了完整起见,程序化解决方案将是:

private TransactionTemplate transactionTemplate;

public setTransactionManager(PlatformTransactionManager transactionManager) {
  this.transactionTemplate = new TransactionTemplate(transactionManager);
}

...

while (true) {

  transactionTemplate.execute(new TransactionCallbackWithoutResult() {
    protected void doInTransactionWithoutResult(TransactionStatus status) {
      try {
        dao.m1(data1);
        dao.m2(data2);
        dao.m3(data3);
        dao.m4(data4);
      } catch(DbUpdateException e) {
        status.setRollbackOnly();
      }
    }
  });
}
于 2009-06-21T15:13:22.733 回答
1

是的,您可以将这些调用放在一个方法中,并以声明方式指定您的事务。

您不需要添加该代码 - Spring 可以为您完成。

于 2009-06-21T13:39:52.470 回答
1

Spring 可以按照说明使用 @Transactional 为您处理这一切,如果您愿意,也可以在 XML 中处理。

正确的导入是您想要的 事务传播类型,这完全取决于您的应用程序。

默认情况下,如果一个事务不存在,则会启动一个事务,如果一个事务已经启动,则会重新使用现有事务。如果您希望所有 4 个 DAO 都是原子的,这就是您想要的行为。

将@Transactional 放在一个将管理名为(MyService)的DAO 方法的类上——该层之下的任何东西现在都将参与该事务边界。

IE:

@Transactional
public void m1(Data data) {
 ...
}

@Transactional
public void m2(Data data) {
 ...
}

在代码中这样做是完全没有必要的。

请参阅此处了解更多信息

于 2009-06-22T09:18:07.630 回答