如何仅使用一个连接在休眠中进行嵌套事务?

Posted

技术标签:

【中文标题】如何仅使用一个连接在休眠中进行嵌套事务?【英文标题】:How do I do nested transactions in hibernate using only one connection? 【发布时间】:2012-06-07 11:01:33 【问题描述】:

我要解决的问题的上下文:我有一个 java spring http 拦截器 AuditHttpCommunicationInterceptor,它可以审计与外部系统的通信。进行通信的 HttpClieant 用于执行某些称为 DoBusinessLogicService 的业务逻辑的 java 服务类。 DoBusinessLogicServices 打开一个新事务并使用几个协作者来做很多事情。

要解决的问题:无论 DoBusinessLogicSevice 中的任何操作的结果如何(意外异常等),我都希望通过 AuditHttpCommunicationInterceptor 将审核存储在数据库中。

我使用的解决方案:AuditHttpCommunicationInterceptor 将以这种方式打开一个新事务:

    TransactionDefinition transactionDefinition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    new TransactionTemplate(platformTransactionManager, transactionDefinition).execute(new TransactionCallbackWithoutResult() 
        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) 
            // do stuff
        
    );

一切正常。当 DoBusinessLogicSevice 的一部分抛出意外异常时,它的事务被回滚,但 AuditHttpCommunicationInterceptor 设法将审计存储在数据库中。

此解决方案产生的问题:AuditHttpCommunicationInterceptor 使用新的数据库连接。因此,对于每个 DoBusinessLogicService 调用,我需要 2 个数据库连接。 基本上,我想知道问题的解决方案:如何让 TransactionTemplate “暂停”当前事务,并在这种情况下将连接重用于新事务。

有什么想法吗? :)

附: 一个想法可能是采用不同的设计方法:删除拦截器并创建一个直接在 DoBusinessLogicSevice 中使用的 AuditingHttpClient(不是由 spring 调用的),但我不能这样做,因为我无法访问那里的所有 http 字段。

【问题讨论】:

如果我理解正确的话,审计事务是在业务事务提交或回滚后启动的。那么为什么它需要第二个连接呢?如果我错了,请尝试解释操作的顺序。 如果你有两种方法:@Transactional(propagation=Propagation.REQUIRES_NEW) doAudit() @Transactional doBusiness() .... .... doAudit(); 这将是两个事务,而 doAudit 将独立于第一个事务 @JB Nizet:这些事务是嵌套的。业务事务开始,做事,http调用被提交的拦截器在一个单独的内部事务中审计,业务事务做更多的事情并提交 @Cris:据我所知,注释驱动的事务与我在上面粘贴的事务之间没有区别。我只是做了你所描述的,但没有使用注释。 @Transactional(propagation=Propagation.REQUIRES_NEW 将使用新的数据库连接,我负担不起。 如果您使用的是连接池,则无论如何都应该重用连接。为什么要经历所有的麻烦?据我所知,Spring 不支持开箱即用地将多个事务绑定到同一个数据库连接。 【参考方案1】:

Spring 支持嵌套事务(propagation="NESTED"),但这确实取决于数据库平台,而且我不相信每个数据库平台都能够处理嵌套事务。

我真的不明白从池中获取连接、执行快速审计事务并返回连接有什么大不了的。

更新:虽然 Spring 支持嵌套事务,但 Hibernate 似乎不支持。如果是这种情况,我会说:使用另一个连接进行审核。

【讨论】:

我们将使用另一个连接,看看效果如何。

以上是关于如何仅使用一个连接在休眠中进行嵌套事务?的主要内容,如果未能解决你的问题,请参考以下文章

EF事务嵌套

VB6 ADO 连接 - 如何检查是不是在事务中?

使用 JDBC 3.0 实现对嵌套事务的支持

Hibernate org.hibernate.TransactionException:jaxrs 不支持嵌套事务

无法打开 JPA EntityManager 进行事务处理;嵌套异常是 org.hibernate.exception.SQLGrammarException:无法获取 JDBC 连接

java 启动jdbc 事务报错 嵌套异常