简体   繁体   English

在Spring启动应用程序中包装事务中的多个调用?

[英]wrapping multiple calls in a transaction in spring boot application?

I am using jdbctemplate to execute queries against db in my spring application. 我正在使用jdbctemplate在我的spring应用程序中对db执行查询。

Here is the method that is annotated with @Transactional 这是使用@Transactional注释的方法

@Transactional
public boolean doSomething(){    
    try {
        jdbcTemplate.update(sql1); //1
        jdbcTemplate.update(sql2); //2
        jdbcTemplate.update(sql3); //3
        return true; 
    } catch (Exception ex){
        return false;
    }
}

My question is if 1 and 2 succeeds and 3 fails, will the transaction on 1 and 2 rolls back or not? 我的问题是,如果1和2成功而3失败,1和2上的交易是否会回滚? How can I test this? 我该怎么测试呢?

Additionally is having a boolean as return value a good practice to indicate the state of transaction? 另外有一个布尔值作为返回值是一个表明交易状态的好习惯吗?

NO! 没有! If you catch the exception your sql will not rollback!!!! 如果你捕获异常,你的sql将不会回滚!

This will not trigger a rollback. 这不会触发回滚。 You need to remove the try-catch. 你需要删除try-catch。 But yes these will rollback as expected if a runtime exception is thrown. 但是,如果抛出运行时异常,这些将按预期回滚。 Please reference the documentation below. 请参考以下文档。

@Transactional settings @Transactional设置

http://docs.spring.io/autorepo/docs/spring/4.2.x/spring-framework-reference/html/transaction.html#transaction-declarative-attransactional-settings http://docs.spring.io/autorepo/docs/spring/4.2.x/spring-framework-reference/html/transaction.html#transaction-declarative-attransactional-settings

You'll see a few lines down that rollbacks are triggered by any RuntimeException. 您会看到几行内容,任何RuntimeException都会触发回滚。 So if you catch the exception it will not trigger a rollback it will simply end the transaction when you return false. 因此,如果您捕获异常,它将不会触发回滚,它将在您返回false时简单地结束事务。 Notice further that it will not rollback if you throw a checked exception so don't try to fix this by throwing an exception to do whatever you were going to do with that boolean return value. 另外请注意,如果抛出一个已检查的异常,它将不会回滚,所以不要试图通过抛出异常来解决这个问题,以便做你要对该布尔返回值做的任何事情。

I haven't tried this myself but it appears you can rollback for checked exceptions if you set the rollbackFor property on @Transactional or maybe just catch RuntimeException on the outside of this method? 我自己没有尝试过,但是如果你在@Transactional上设置rollbackFor属性或者在这个方法的外部捕获RuntimeException,你似乎可以回滚检查异常? Or throw your own Runtime Exception? 或抛出自己的运行时异常? I leave that to you. 我把它留给你。

As asked above this also works for repositories you can see an example here 如上所述,这也适用于存储库,您可以在此处查看示例

Spring Data(Repositories) transactions Spring Data(Repositories)事务

http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#transactions

If 3 fails, 1 and 2 will rollback. 如果3失败,则1和2将回滚。 This is the core point of transactions (units of work). 这是交易的核心点(工作单位)。
IMPORTANT CORRECTION based on @Zergleb's answer : only if you throw an exception. 基于@ Zergleb答案的重要更正 :仅当您抛出异常时。 In your code you're munching the exception, so 1 and 2 will persist, since the transaction doesn't "see" the exception it isn't aware anything has gone wrong. 在你的代码中,你正在咀嚼异常,因此1和2将持续存在,因为事务没有“看到”异常它不知道出现了什么问题。

To test, put some invalid sql in sql3 , see what happens. 要测试,在sql3放入一些无效的sql,看看会发生什么。

I would generally not return a boolean to indicate success. 我通常不会返回一个布尔值来表示成功。 Success is the successful completion of the method, you should instead let the exception bubble up or wrap the exception in something more appropriate and throw that, if your scenario indicates such. 成功是方法的成功完成,你应该让异常冒泡或将异常包装在更合适的东西中,并抛出它,如果你的场景表明这样。

For example: 例如:

@Transactional
public void doSomething(){
    try {
        jdbcTemplate.update(sql1); //1
        jdbcTemplate.update(sql2); //2
        jdbcTemplate.update(sql3); //3
    } catch (Exception ex){
        throw new MyCustomPersistenceException("Could not doSomething", e);
    }
}

if 1 and 2 succeeds and 3 fails, will the transaction on 1 and 2 rolls back or not? 如果1和2成功而3失败,1和2上的交易是否会回滚?

If the third operation fails, the first and second operations will be rollback. 如果第三个操作失败,则第一个和第二个操作将回滚。 But if they are part of the same transaction or transaction context. 但如果它们是同一事务或事务上下文的一部分。

For example, if you define your transaction manager as DataSourceTransactionManager it will rollback the JDBC operations of the same connection. 例如,如果将事务管理器定义为DataSourceTransactionManager,它将回滚同一连接的JDBC操作。 In your case, you have all three operations inside the same method and are using the same jdbcTemplate, so it will rolback your other two transactions. 在您的情况下,您在同一方法中拥有所有三个操作并使用相同的jdbcTemplate,因此它将回滚您的其他两个事务。

You can test this if make a sql instruction to fail, for example: 如果使sql指令失败,您可以测试这个,例如:

  1. INSERT correct INSERT正确
  2. INSERT correct INSERT正确
  3. INSERT but you can try to insert a String in a Number column, or a null on a not null column. INSERT但您可以尝试在Number列中插入String,或在非null列上插入null。

You can see more here http://www.journaldev.com/2603/spring-transaction-management-jdbc-example 你可以在这里看到更多http://www.journaldev.com/2603/spring-transaction-management-jdbc-example

http://docs.spring.io/autorepo/docs/spring/4.2.x/spring-framework-reference/html/transaction.html http://docs.spring.io/autorepo/docs/spring/4.2.x/spring-framework-reference/html/transaction.html

About returning boolean I think it's better to throw an exception, and it will rollback the transaction automatically. 关于返回布尔值我认为抛出异常更好,它会自动回滚事务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM