java 使用 Spring JDBC 的简单事务?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1023907/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 14:50:46  来源:igfitidea点击:

Easy transactions using Spring JDBC?

javaspringjdbctransactionsrollback

提问by letronje

I am working on a Java app that uses Spring IoCand JDBC Template classes. I have a DAO class that has 4 methods : m1() to m4(). m1 performs multiple inserts and updates on table t1, m2 on table t2, m3 on t3, etc.

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

The DAO methods are used as follows:

DAO 方法的使用如下:

while(true)
{
  //process & generate data

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

  //sleep
}

I want the db operations under the 4 consecutive method calls to be atomic, either all the 4 tables are updated successfully or none are. So, if there is an error while performing operations in m3(), i want to rollback all the changes(updates & inserts) performed in m2 & m1.

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

So does spring let you do it the following way ?

那么 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

}

}

or are there better ways to do it?

或者有更好的方法吗?

采纳答案by Maarten Winkels

For completeness, the programmatic solution would be:

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

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();
      }
    }
  });
}

回答by cletus

Yes Spring allows you to programmatically control transactions.

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

Personally I prefer declarative transactionsusing annotations, which goes like this:

我个人更喜欢使用注释的声明式事务,它是这样的:

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);
}

where the DAO functions are defined:

其中定义了 DAO 函数:

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

This requires in your applicationContext.xml:

这需要在您的applicationContext.xml 中

<tx:annotation-driven/>

Declarative transactions can be declared to require a transaction, require a new transaction, support transactions, etc. Rollback will occur when a block annotated with @Transactionalthrows a RuntimeException.

声明性事务可以声明为需要一个事务、需要一个新事务、支持事务等。当一个用@Transactionalthrows注释的块时会发生回滚RuntimeException

回答by JARC

Spring can handle this all for you by using @Transactional as explained or in XML if you'd prefer.

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

The import thing to get right is the type of Transaction Propagationyou want which all depends on your application.

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

By default a transaction will be started if one doesn't exist, and will re-use an existing transaction if one has already been started. This is the behavior you want if you want all 4 DAOs to be atomic.

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

Put @Transactional on a class which will manage the DAO methods called (MyService) - anything below this layer will now take part in that transaction boundary.

将@Transactional 放在一个类上,该类将管理名为 (MyService) 的 DAO 方法 - 此层以下的任何内容现在都将参与该事务边界。

i.e:

IE:

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

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

Doing this in code is completely unnecessary.

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

See here for more info

此处获得更多信息

回答by duffymo

Yes, you can put those calls inside a method and specify your transactions declaratively.

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

You don't need to add that code - Spring can do it for you.

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