gpt4 book ai didi

spring - 具有不同传播的 @Transactional 超时属性如何工作

转载 作者:行者123 更新时间:2023-12-01 14:37:40 27 4
gpt4 key购买 nike

我对@Transactional 的行为感到困惑超时 属性

我有以下顺序

Main -> 
UserExecutionServiceImpl.executeRecordInvoice ->
ProcessInvoiceServiceImpl.recordInvoice ->
WarehouseServiceImpl.checkStockAvailability

强制回滚异常 超时 设置为 0。

executeRecordInvoice @Transactional(timeout=0)抛出异常并停止所有。有道理

executeRecordInvoice @Transactional记录发票@Transactional(timeout=0)不抛出异常。实际上超时值已被忽略。

我可以假设,因为交易确实是从 开始的。 executeRecordInvoice 此外,因为这两种方法默认都有 Propagation.Required ,这意味着,第二个 ( recordInvoice ) 被考虑在第一个 ( executeRecordInvoice ) 中,已经存在的事务,它正在运行

更重要的是,我做了两个简单的实验:
  • executeRecordInvoice @Transactional记录发票@Transactional(propagation.Propagation.REQUIRES_NEW, timeout=0)抛出异常。现在有效,因为 新品 交易开始于 记录发票因此 超时 被认为。
  • 从 Main 类直接调用 ProcessInvoiceServiceImpl.recordInvoice ,它与 @Transactional(propagation.Propagation.REQUIRED, timeout=0)或与 @Transactional(propagation.Propagation.REQUIRES_NEW, timeout=0) ,再次超时 被认为。

  • 到这里为止,我很好,一切都有道理。但是对 应用 1 和 2 WarehouseServiceImpl.checkStockAvailability , 这是行不通的:
  • executeRecordInvoice 记录发票@Transactional (因此默认情况下都是 Propagation.REQUIRED)和 checkStockAvailability @Transactional(propagation.Propagation.REQUIRES_NEW, timeout=0) .异常(exception)是 不是 扔了!。
  • 从 Main 类直接调用 WarehouseServiceImpl.checkStockAvailability ,它与 @Transactional(propagation.Propagation.REQUIRED, timeout=0)或与 @Transactional(propagation.Propagation.REQUIRES_NEW, timeout=0) ,再次超时 不是 经过考虑的。

  • 类声明
    @Service
    @Transactional
    @Scope("prototype")
    public class WarehouseServiceImpl implements WarehouseService {

    // Unique method implementation
    @Transactional(propagation = Propagation.REQUIRES_NEW, timeout=0)
    public boolean checkStockAvailability(Product product, BigDecimal quantity) {

    ...

    return true;

    }
    }

    欢迎任何想法或建议。

    Spring 框架 4.0.5

    谢谢你。

    在做了安德烈的建议之后,我有以下几点:
    @Transactional
    @Scope("prototype")
    @Service("processInvoiceService")
    public class ProcessInvoiceServiceImpl implements ProcessInvoiceService {

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, timeout=0)
    public void recordInvoice(InvoiceHeader invoiceHeader) {

    在 MainTest 类中
    ProcessInvoiceService processInvoiceService = context.getBean(ProcessInvoiceService.class);

    try{
    processInvoiceService.recordInvoice(invoiceHeader03);
    }
    catch(Exception e){
    logger.error("ERROR ALFA: {}", e.getMessage());
    }

    随着显示控制台,部分结果输出
    Creating instance of bean 'processInvoiceService'
    20:16:57,320 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'productService'
    20:16:57,320 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'invoiceHeaderService'
    20:16:57,320 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'invoiceDetailService'
    20:16:57,321 DEBUG ctory.support.DefaultListableBeanFactory: 449 - Creating instance of bean 'warehouseServiceImpl'
    20:16:57,321 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
    20:16:57,321 DEBUG xy.InfrastructureAdvisorAutoProxyCreator: 593 - Creating implicit proxy for bean 'warehouseServiceImpl' with 0 common interceptors and 1 specific interceptors
    20:16:57,321 DEBUG amework.aop.framework.JdkDynamicAopProxy: 117 - Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [com.manuel.jordan.model.service.support.impl.WarehouseServiceImpl@7b4c50bc]
    20:16:57,321 DEBUG ctory.support.DefaultListableBeanFactory: 477 - Finished creating instance of bean 'warehouseServiceImpl'
    20:16:57,322 INFO e.process.impl.ProcessInvoiceServiceImpl: 46 - ProcessInvoiceServiceImpl arg constructor
    20:16:57,322 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
    20:16:57,322 DEBUG xy.InfrastructureAdvisorAutoProxyCreator: 593 - Creating implicit proxy for bean 'processInvoiceService' with 0 common interceptors and 1 specific interceptors
    20:16:57,322 DEBUG amework.aop.framework.JdkDynamicAopProxy: 117 - Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [com.manuel.jordan.model.service.process.impl.ProcessInvoiceServiceImpl@5884a914]
    20:16:57,322 DEBUG ctory.support.DefaultListableBeanFactory: 477 - Finished creating instance of bean 'processInvoiceService'
    20:16:57,322 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
    20:16:57,322 DEBUG .datasource.DataSourceTransactionManager: 367 - Creating new transaction with name [com.manuel.jordan.model.service.process.impl.ProcessInvoiceServiceImpl.recordInvoice]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT,timeout_0; ''
    20:16:57,322 DEBUG k.jdbc.datasource.SimpleDriverDataSource: 138 - Creating new JDBC Driver Connection to [jdbc:hsqldb:mem:testdb]
    20:16:57,323 DEBUG .datasource.DataSourceTransactionManager: 206 - Acquired Connection [org.hsqldb.jdbc.JDBCConnection@50378a4] for JDBC transaction
    20:16:57,323 DEBUG .datasource.DataSourceTransactionManager: 223 - Switching JDBC Connection [org.hsqldb.jdbc.JDBCConnection@50378a4] to manual commit
    20:16:57,323 INFO e.process.impl.ProcessInvoiceServiceImpl: 59 - ProcessInvoiceServiceImpl recordInvoice - start
    20:16:57,323 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
    20:16:57,323 DEBUG .datasource.DataSourceTransactionManager: 472 - Participating in existing transaction
    20:16:57,323 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
    20:16:57,323 DEBUG .datasource.DataSourceTransactionManager: 472 - Participating in existing transaction
    20:16:57,324 DEBUG g.springframework.jdbc.core.JdbcTemplate: 908 - Executing prepared SQL update
    20:16:57,324 DEBUG g.springframework.jdbc.core.JdbcTemplate: 627 - Executing prepared SQL statement [INSERT INTO invoiceheader(id, number, date, total) VALUES(?, ?, ?, ?)]
    20:16:57,324 DEBUG .datasource.DataSourceTransactionManager: 854 - Participating transaction failed - marking existing transaction as rollback-only
    20:16:57,324 DEBUG .datasource.DataSourceTransactionManager: 295 - Setting JDBC transaction [org.hsqldb.jdbc.JDBCConnection@50378a4] rollback-only
    20:16:57,324 DEBUG .datasource.DataSourceTransactionManager: 854 - Participating transaction failed - marking existing transaction as rollback-only
    20:16:57,325 DEBUG .datasource.DataSourceTransactionManager: 295 - Setting JDBC transaction [org.hsqldb.jdbc.JDBCConnection@50378a4] rollback-only
    20:16:57,325 DEBUG .datasource.DataSourceTransactionManager: 847 - Initiating transaction rollback
    20:16:57,325 DEBUG .datasource.DataSourceTransactionManager: 281 - Rolling back JDBC transaction on Connection [org.hsqldb.jdbc.JDBCConnection@50378a4]
    20:16:57,325 DEBUG .datasource.DataSourceTransactionManager: 324 - Releasing JDBC Connection [org.hsqldb.jdbc.JDBCConnection@50378a4] after transaction
    20:16:57,325 DEBUG ramework.jdbc.datasource.DataSourceUtils: 327 - Returning JDBC Connection to DataSource
    20:16:57,325 ERROR com.manuel.jordan.main.MainTest: 93 - ERROR ALFA: Transaction timed out: deadline was Mon Jun 30 20:16:57 PET 2014
    20:16:57,325 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'

    错误消息出现在预期中..

    现在是其他类(class)
    @Service
    @Transactional
    @Scope("prototype")
    public class WarehouseServiceImpl implements WarehouseService {

    private static final Logger logger = LoggerFactory.getLogger(WarehouseServiceImpl.class);

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, timeout=0)
    public boolean checkStockAvailability(Product product, BigDecimal quantity) {

    在 MainTest 类中
    WarehouseService warehouseService = context.getBean(WarehouseService.class);

    try{
    logger.info("Pre");
    boolean result = warehouseService.checkStockAvailability(product01, BigDecimal.ZERO);
    logger.info("result: {}", result);
    logger.info("Post");
    }
    catch(Exception e){
    logger.error("ERROR BETA: {}", e.getMessage());
    }

    随着显示控制台,部分结果输出
    20:16:57,337 DEBUG ctory.support.DefaultListableBeanFactory: 449 - Creating instance of bean 'warehouseServiceImpl'
    20:16:57,337 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
    20:16:57,338 DEBUG xy.InfrastructureAdvisorAutoProxyCreator: 593 - Creating implicit proxy for bean 'warehouseServiceImpl' with 0 common interceptors and 1 specific interceptors
    20:16:57,338 DEBUG amework.aop.framework.JdkDynamicAopProxy: 117 - Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [com.manuel.jordan.model.service.support.impl.WarehouseServiceImpl@23f5b5dc]
    20:16:57,338 DEBUG ctory.support.DefaultListableBeanFactory: 477 - Finished creating instance of bean 'warehouseServiceImpl'
    20:16:57,338 INFO com.manuel.jordan.main.MainTest: 102 - Pre
    20:16:57,338 DEBUG ion.AnnotationTransactionAttributeSource: 108 - Adding transactional method 'WarehouseServiceImpl.checkStockAvailability' with attribute: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT,timeout_0; ''
    20:16:57,338 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
    20:16:57,339 DEBUG .datasource.DataSourceTransactionManager: 367 - Creating new transaction with name [com.manuel.jordan.model.service.support.impl.WarehouseServiceImpl.checkStockAvailability]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT,timeout_0; ''
    20:16:57,339 DEBUG k.jdbc.datasource.SimpleDriverDataSource: 138 - Creating new JDBC Driver Connection to [jdbc:hsqldb:mem:testdb]
    20:16:57,339 DEBUG .datasource.DataSourceTransactionManager: 206 - Acquired Connection [org.hsqldb.jdbc.JDBCConnection@34bde49d] for JDBC transaction
    20:16:57,339 DEBUG .datasource.DataSourceTransactionManager: 223 - Switching JDBC Connection [org.hsqldb.jdbc.JDBCConnection@34bde49d] to manual commit
    20:16:57,339 DEBUG .datasource.DataSourceTransactionManager: 755 - Initiating transaction commit
    20:16:57,339 DEBUG .datasource.DataSourceTransactionManager: 266 - Committing JDBC transaction on Connection [org.hsqldb.jdbc.JDBCConnection@34bde49d]
    20:16:57,339 DEBUG .datasource.DataSourceTransactionManager: 324 - Releasing JDBC Connection [org.hsqldb.jdbc.JDBCConnection@34bde49d] after transaction
    20:16:57,339 DEBUG ramework.jdbc.datasource.DataSourceUtils: 327 - Returning JDBC Connection to DataSource
    20:16:57,339 INFO com.manuel.jordan.main.MainTest: 104 - result: true
    20:16:57,339 INFO com.manuel.jordan.main.MainTest: 105 - Post

    错误没有像预期的那样抛出..

    欧姆龙

    新的更新代码:
    @Service
    @Transactional
    @Scope("prototype")
    public class WarehouseServiceImpl implements WarehouseService {

    private static final Logger logger = LoggerFactory.getLogger(WarehouseServiceImpl.class);

    private ProductService productService;

    @Autowired
    public WarehouseServiceImpl(ProductService productService){
    this.productService = productService;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, timeout=0)
    public boolean checkStockAvailability(Product product, BigDecimal quantity) {

    logger.info("Amount: {}", this.productService.getAmountProducts());
    ...
    return true;

    }

    }

    上面显示的代码对于两个项目是一样的,一个使用JdbcTemplate,一切OK,抛出了预期的错误,但另一个使用Hibernate的项目没有抛出预期的错误。在结果输出下方。
    08:27:06,782  INFO          com.manuel.jordan.main.MainTest: 102 - Pre
    08:27:06,782 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
    08:27:06,782 DEBUG m.hibernate4.HibernateTransactionManager: 367 - Creating new transaction with name [com.manuel.jordan.model.service.support.impl.WarehouseServiceImpl.checkStockAvailability]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT,timeout_0; ''
    08:27:06,783 DEBUG m.hibernate4.HibernateTransactionManager: 417 - Opened new Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@57ce634f updates=org.hibernate.engine.spi.ExecutableList@b8a7e43 deletions=org.hibernate.engine.spi.ExecutableList@35835fa orphanRemovals=org.hibernate.engine.spi.ExecutableList@56f71edb collectionCreations=org.hibernate.engine.spi.ExecutableList@7207cb51 collectionRemovals=org.hibernate.engine.spi.ExecutableList@2a27cb34 collectionUpdates=org.hibernate.engine.spi.ExecutableList@6892cc6f collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@6fd1660 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
    08:27:06,783 DEBUG m.hibernate4.HibernateTransactionManager: 427 - Preparing JDBC Connection of Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@57ce634f updates=org.hibernate.engine.spi.ExecutableList@b8a7e43 deletions=org.hibernate.engine.spi.ExecutableList@35835fa orphanRemovals=org.hibernate.engine.spi.ExecutableList@56f71edb collectionCreations=org.hibernate.engine.spi.ExecutableList@7207cb51 collectionRemovals=org.hibernate.engine.spi.ExecutableList@2a27cb34 collectionUpdates=org.hibernate.engine.spi.ExecutableList@6892cc6f collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@6fd1660 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
    08:27:06,783 DEBUG gine.jdbc.internal.LogicalConnectionImpl: 226 - Obtaining JDBC connection
    08:27:06,783 DEBUG k.jdbc.datasource.SimpleDriverDataSource: 138 - Creating new JDBC Driver Connection to [jdbc:hsqldb:mem:testdb]
    08:27:06,783 DEBUG gine.jdbc.internal.LogicalConnectionImpl: 232 - Obtained JDBC connection
    08:27:06,783 DEBUG .transaction.spi.AbstractTransactionImpl: 160 - begin
    08:27:06,783 DEBUG ransaction.internal.jdbc.JdbcTransaction: 69 - initial autocommit status: true
    08:27:06,783 DEBUG ransaction.internal.jdbc.JdbcTransaction: 71 - disabling autocommit
    08:27:06,784 DEBUG m.hibernate4.HibernateTransactionManager: 488 - Exposing Hibernate transaction as JDBC transaction [org.hsqldb.jdbc.JDBCConnection@4a6c18ad]
    08:27:06,784 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
    08:27:06,784 DEBUG m.hibernate4.HibernateTransactionManager: 362 - Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@57ce634f updates=org.hibernate.engine.spi.ExecutableList@b8a7e43 deletions=org.hibernate.engine.spi.ExecutableList@35835fa orphanRemovals=org.hibernate.engine.spi.ExecutableList@56f71edb collectionCreations=org.hibernate.engine.spi.ExecutableList@7207cb51 collectionRemovals=org.hibernate.engine.spi.ExecutableList@2a27cb34 collectionUpdates=org.hibernate.engine.spi.ExecutableList@6892cc6f collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@6fd1660 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
    08:27:06,784 DEBUG m.hibernate4.HibernateTransactionManager: 472 - Participating in existing transaction
    08:27:06,784 DEBUG ctory.support.DefaultListableBeanFactory: 249 - Returning cached instance of singleton bean 'transactionManager'
    08:27:06,784 DEBUG m.hibernate4.HibernateTransactionManager: 362 - Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@57ce634f updates=org.hibernate.engine.spi.ExecutableList@b8a7e43 deletions=org.hibernate.engine.spi.ExecutableList@35835fa orphanRemovals=org.hibernate.engine.spi.ExecutableList@56f71edb collectionCreations=org.hibernate.engine.spi.ExecutableList@7207cb51 collectionRemovals=org.hibernate.engine.spi.ExecutableList@2a27cb34 collectionUpdates=org.hibernate.engine.spi.ExecutableList@6892cc6f collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@6fd1660 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
    08:27:06,784 DEBUG m.hibernate4.HibernateTransactionManager: 472 - Participating in existing transaction
    08:27:06,785 DEBUG org.hibernate.SQL: 109 - select count(*) as col_0_0_ from product product0_
    08:27:06,785 DEBUG org.hibernate.loader.Loader: 951 - Result set row: 0
    08:27:06,786 DEBUG org.hibernate.loader.Loader:1485 - Result row:
    08:27:06,786 INFO ervice.support.impl.WarehouseServiceImpl: 45 - Amount: 6
    08:27:06,786 DEBUG m.hibernate4.HibernateTransactionManager: 755 - Initiating transaction commit
    08:27:06,786 DEBUG m.hibernate4.HibernateTransactionManager: 551 - Committing Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@57ce634f updates=org.hibernate.engine.spi.ExecutableList@b8a7e43 deletions=org.hibernate.engine.spi.ExecutableList@35835fa orphanRemovals=org.hibernate.engine.spi.ExecutableList@56f71edb collectionCreations=org.hibernate.engine.spi.ExecutableList@7207cb51 collectionRemovals=org.hibernate.engine.spi.ExecutableList@2a27cb34 collectionUpdates=org.hibernate.engine.spi.ExecutableList@6892cc6f collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@6fd1660 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
    08:27:06,786 DEBUG .transaction.spi.AbstractTransactionImpl: 175 - committing
    08:27:06,786 DEBUG ransaction.internal.jdbc.JdbcTransaction: 113 - committed JDBC Connection
    08:27:06,786 DEBUG ransaction.internal.jdbc.JdbcTransaction: 126 - re-enabling autocommit
    08:27:06,787 DEBUG m.hibernate4.HibernateTransactionManager: 633 - Closing Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=org.hibernate.engine.spi.ExecutableList@57ce634f updates=org.hibernate.engine.spi.ExecutableList@b8a7e43 deletions=org.hibernate.engine.spi.ExecutableList@35835fa orphanRemovals=org.hibernate.engine.spi.ExecutableList@56f71edb collectionCreations=org.hibernate.engine.spi.ExecutableList@7207cb51 collectionRemovals=org.hibernate.engine.spi.ExecutableList@2a27cb34 collectionUpdates=org.hibernate.engine.spi.ExecutableList@6892cc6f collectionQueuedOps=org.hibernate.engine.spi.ExecutableList@6fd1660 unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] after transaction
    08:27:06,787 DEBUG gine.jdbc.internal.LogicalConnectionImpl: 246 - Releasing JDBC connection
    08:27:06,787 DEBUG gine.jdbc.internal.LogicalConnectionImpl: 264 - Released JDBC connection
    08:27:06,787 INFO com.manuel.jordan.main.MainTest: 104 - result: true
    08:27:06,787 INFO com.manuel.jordan.main.MainTest: 105 - Post

    有什么线索吗?数据访问当然存在......

    最佳答案

    查看您的第一个日志(与 recordInvoicecheckStockAvailability 的超时问题相关),这些确实表明事务行为已正确应用:在 Java 代码级别事务已启动并提交。日志的唯一区别在于 recordInvoice正在对数据库执行实际查询,同时使用 checkStockAvailability哪有这回事。

    对此的一个可能答案是,如果数据库没有事件,则没有数据库级事务。您在 Java 代码中的内容反射(reflect)在 db 级别。例如,如果您打开一个 MySQL 控制台并在表中插入一些内容,那么最后您需要提交才能在 DB 中查看结果。

    与您的第二个问题相关,您在哪里使用 JdbcTemplate对于一项测试和 Hibernate(使用 HibernateTransactionManager)进行另一项测试,查看 source code for the Hibernate transaction似乎只考虑严格大于 0 的值。因此,一个简单的测试涉及在事务方法中将超时设置为一秒 checkStockAvailability可以添加一个 Thread.sleep(1500)可能会显示超时的 0 秒值被简单地忽略,解释了您的测试结果。

    关于spring - 具有不同传播的 @Transactional 超时属性如何工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24479302/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com