gpt4 book ai didi

java - @Transactional 注释未按预期工作

转载 作者:太空宇宙 更新时间:2023-11-04 11:35:29 30 4
gpt4 key购买 nike

我需要一些帮助来尝试调试为什么我的 Spring Boot 应用程序的事务管理不起作用。

基本思想是,我有 2 个表,我想在其中写入一些内容。当 2 个表之一出现任何问题时,应该回滚事务,并且不应该向数据库写入任何内容。

这是代码的简化版本:

@Transactional
public void archiveTask(String taskId) {

OffloadedRun run = new OffloadedRun();
run.setStartDateTime(LocalDateTime.now());
calculationRunRepository.save(run);

List<SingleContractCalculationResults> activeResults = contractCalculationResultAccessService.get(taskId);

for (SingleContractCalculationResults result : example) {
for (Map.Entry<String, ContractResults> entry : result.getResultsPerScenario().entrySet()) {
String scenario = entry.getKey();
ContractResults results = entry.getValue();

OffloadedCalculationResult offloadedCalculationResult = new OffloadedCalculationResult();

// offloadedCalculationResult.setOffloadedRun(run);
offloadedCalculationResult.setContractId(result.getContractId());
calculationResultRepository.save(offloadedCalculationResult);
}
}
}

我执行保存方法的类是 Spring Data JPA 存储库,其定义如下:

public interface CalculationRunRepository extends JpaRepository<OffloadedRun, String> {
}

我注释掉的行是必填列。我这样做是为了强制 ConstraintViolationException 来测试在第二个表中保存某些内容时发生的异常情况。

发生的情况是第一个实体已成功保存,这是不应该发生的。我正在尝试找出原因。

我的 Spring Boot 应用程序配置了 @EnableTransactionManagement 以在我自己的服务中启用 @Transactional 注释(就像这个)。

我将 org.springframework.transaction.interceptor 的日志记录级别更改为 TRACE 以查看发生了什么:

o.s.t.i.TransactionInterceptor           : Getting transaction for [be.sodemo.calculator.offloading.TaskArchiverImpl.archiveTask]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.save]
o.s.t.i.TransactionInterceptor : Completing transaction for [be.sodemo.calculator.offloading.TaskArchiverImpl.archiveTask]

o.h.e.j.s.SqlExceptionHelper : SQL Error: 1048, SQLState: 23000
o.h.e.j.s.SqlExceptionHelper : Column 'run_id' cannot be null
o.h.e.j.b.i.AbstractBatchImpl : HHH000010: On release of batch it still contained JDBC statements
o.a.c.c.C.[.[.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement] with root cause

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'run_id' cannot be null
at sun.reflect.GeneratedConstructorAccessor2599.newInstance(Unknown Source) ~[?:?]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java) ~[?:1.8.0_102]
at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_102]
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425) ~[mysql-connector-java-5.1.40.jar:5.1.40]

在此之后

我不确定如果事务管理正常工作,日志记录会是什么样子,但看起来它正在完成每一个事务。

有人知道我接下来可以尝试什么来看看出了什么问题吗?

编辑:到目前为止,我一直在使用 MySQL 数据库。我注意到,当我在 H2 数据库上测试完全相同的代码时,回滚似乎按预期工作。我看到的唯一区别是它抛出了另一个特定于供应商的异常。

我尝试在 @Transactional 注释上显式设置 rollbackFor 属性,如下所示:

@Transactional(rollbackFor = {Exception.class, MySQLIntegrityConstraintViolationException.class})

但即便如此也没有导致回滚。

编辑:

这些是我与 JPA/Hibernate 相关的 Spring Boot 设置:

spring:
jpa:
hibernate:
ddl-auto: none
dialect: org.hibernate.dialect.MySQL5Dialect
database: mysql
properties:
hibernate:
order_inserts: true
jdbc:
batch_size: 50
datasource:
url: jdbc:mysql://localhost/local-test-db
driver-class-name: com.mysql.jdbc.Driver

最佳答案

请验证您在应用程序中使用的是单个数据源还是多个数据源。

如果您使用单个数据源,那么@Transactional将默认选择该单个数据源,否则它将从多个数据源中选择任何一个,并且会发生这种类型的无法追踪的问题。

请看一下 @Transaction annotation with different data sources

我已经使用解决了该问题

/* This code is present in @Configuration class */
@Bean(name = "postgresDataSource")
DataSource postgresDataSource(){
// DataSource configuration code
}

@Bean(name = "postgresTransactionManager")
public PlatformTransactionManager transactionManager(@Qualifier("postgresDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}

/* This code is present in @Service class */
@Override
@Transactional("postgresTransactionManager")
public void save(Map queueMsg) {
// Transaction specific code
}

关于java - @Transactional 注释未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43343568/

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