java - Spring 批处理 datasource 设置更改应用程序事务的行为

在我的 Spring 引导应用程序中,我有一个 JNDI datasource 配置如下:

spring:
  datasource:
    jndi-name: java:/users

在引入 Spring Batch 之后,一些 REST 服务的行为发生了变化。

例如,以前的服务有这个日志:

2022-05-19 12:56:27.348 TRACE 667690 --- [default task-1] o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'transactionManager'
2022-05-19 12:56:27.349 DEBUG 667690 --- [default task-1] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(281567772<open>)] for JPA transaction
2022-05-19 12:56:27.349 DEBUG 667690 --- [default task-1] o.s.orm.jpa.JpaTransactionManager        : Creating new transaction with name [it.ipzs.sgdd.service.UserService.createDelegation]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2022-05-19 12:56:27.349 DEBUG 667690 --- [default task-1] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@7bac569f]
2022-05-19 12:56:27.349 TRACE 667690 --- [default task-1] o.s.t.i.TransactionInterceptor           : Getting transaction for [it.ipzs.sgdd.service.UserService.createDelegation]
2022-05-19 12:56:27.358 DEBUG 667690 --- [default task-1] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(281567772<open>)] for JPA transaction
2022-05-19 12:56:27.358 DEBUG 667690 --- [default task-1] o.s.orm.jpa.JpaTransactionManager        : Participating in existing transaction
2022-05-19 12:56:27.358 TRACE 667690 --- [default task-1] o.s.t.i.TransactionInterceptor           : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll]
2022-05-19 12:56:27.361 TRACE 667690 --- [default task-1] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll]
2022-05-19 12:56:27.432 TRACE 667690 --- [default task-1] o.s.t.i.TransactionInterceptor           : No need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.countAllBystate]: This method is not transactional.
2022-05-19 12:56:27.437 TRACE 667690 --- [default task-1] o.s.t.i.TransactionInterceptor           : No need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findByUser]: This method is not transactional.
2022-05-19 12:56:27.442 TRACE 667690 --- [default task-1] o.s.t.i.TransactionInterceptor           : No need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findByFiscalnumber]: This method is not transactional.
2022-05-19 12:56:27.446 DEBUG 667690 --- [default task-1] o.s.orm.jpa.JpaTransactionManager        : Found thread-bound EntityManager [SessionImpl(281567772<open>)] for JPA transaction
2022-05-19 12:56:27.446 DEBUG 667690 --- [default task-1] o.s.orm.jpa.JpaTransactionManager        : Suspending current transaction, creating new transaction with name [it.ipzs.sgdd.service.SystemService.getKey]
2022-05-19 12:56:27.447 DEBUG 667690 --- [default task-1] o.s.orm.jpa.JpaTransactionManager        : Opened new EntityManager [SessionImpl(1976763709<open>)] for JPA transaction
2022-05-19 12:56:27.531 DEBUG 667690 --- [default task-1] o.s.orm.jpa.JpaTransactionManager        : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@67f4dd10]
2022-05-19 12:56:27.531 TRACE 667690 --- [default task-1] o.s.t.i.TransactionInterceptor           : Getting transaction for [it.ipzs.sgdd.service.SystemService.getKey]

现在同一个服务有这个其他日志:

2022-05-19 10:15:52.150 TRACE 661470 --- [default task-1] o.s.b.f.s.DefaultListableBeanFactory     : Returning cached instance of singleton bean 'transactionManager'
2022-05-19 10:15:52.150 DEBUG 661470 --- [default task-1] o.s.j.d.DataSourceTransactionManager     : Creating new transaction with name [it.ipzs.sgdd.service.UserService.createDelegation]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2022-05-19 10:15:52.150 DEBUG 661470 --- [default task-1] o.s.j.d.DataSourceTransactionManager     : Acquired Connection [org.jboss.jca.adapters.jdbc.jdk8.WrappedConnectionJDK8@2e37bdd7] for JDBC transaction
2022-05-19 10:15:52.150 DEBUG 661470 --- [default task-1] o.s.j.d.DataSourceTransactionManager     : Switching JDBC Connection [org.jboss.jca.adapters.jdbc.jdk8.WrappedConnectionJDK8@2e37bdd7] to manual commit
2022-05-19 10:15:52.150 TRACE 661470 --- [default task-1] o.s.t.i.TransactionInterceptor           : Getting transaction for [it.ipzs.sgdd.service.UserService.createDelegation]
2022-05-19 10:15:52.157 DEBUG 661470 --- [default task-1] o.s.j.d.DataSourceTransactionManager     : Participating in existing transaction
2022-05-19 10:15:52.157 TRACE 661470 --- [default task-1] o.s.t.i.TransactionInterceptor           : Getting transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll]
2022-05-19 10:15:52.157 DEBUG 661470 --- [default task-1] r$ExtendedEntityManagerInvocationHandler : Starting resource-local transaction on application-managed EntityManager [SessionImpl(184588778<open>)]
2022-05-19 10:15:52.157 DEBUG 661470 --- [default task-1] r$ExtendedEntityManagerInvocationHandler : Joined local transaction
2022-05-19 10:15:52.160 TRACE 661470 --- [default task-1] o.s.t.i.TransactionInterceptor           : Completing transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findAll]
2022-05-19 10:15:52.213 TRACE 661470 --- [default task-1] o.s.t.i.TransactionInterceptor           : No need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.countAllBystate]: This method is not transactional.
2022-05-19 10:15:52.217 TRACE 661470 --- [default task-1] o.s.t.i.TransactionInterceptor           : No need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findByUser]: This method is not transactional.
2022-05-19 10:15:52.220 TRACE 661470 --- [default task-1] o.s.t.i.TransactionInterceptor           : No need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findByFiscalnumber]: This method is not transactional.
2022-05-19 10:15:52.224 DEBUG 661470 --- [default task-1] o.s.j.d.DataSourceTransactionManager     : Suspending current transaction, creating new transaction with name [it.ipzs.sgdd.service.SystemService.getKey]
2022-05-19 10:15:52.300 DEBUG 661470 --- [default task-1] o.s.j.d.DataSourceTransactionManager     : Acquired Connection [org.jboss.jca.adapters.jdbc.jdk8.WrappedConnectionJDK8@6cd14b57] for JDBC transaction
2022-05-19 10:15:52.300 DEBUG 661470 --- [default task-1] o.s.j.d.DataSourceTransactionManager     : Switching JDBC Connection [org.jboss.jca.adapters.jdbc.jdk8.WrappedConnectionJDK8@6cd14b57] to manual commit
2022-05-19 10:15:52.300 TRACE 661470 --- [default task-1] o.s.t.i.TransactionInterceptor           : Getting transaction for [it.ipzs.sgdd.service.SystemService.getKey]

请注意使用 DataSourceTransactionManager 而不是 JpaTransactionManager。

我相信不同的行为是由于以下配置造成的,但我不知道如何在不改变应用程序其余部分的行为的情况下做到这一点:

@Bean
    BatchConfigurer myBatchConfigurer(@Qualifier("dataSource") DataSource dataSource,
                                      ExecutionContextSerializer executionContextSerializer,
                                      PlatformTransactionManager transactionManager) {
        return new DefaultBatchConfigurer(dataSource) {
            @Override
            protected JobExplorer createJobExplorer() throws Exception {
                JobExplorerFactoryBean jobExplorerFactoryBean = new JobExplorerFactoryBean();
                jobExplorerFactoryBean.setDataSource(dataSource);
                jobExplorerFactoryBean
                        .setSerializer(executionContextSerializer);
                jobExplorerFactoryBean.afterPropertiesSet();
                return jobExplorerFactoryBean.getObject();
            }

            @Override
            protected JobRepository createJobRepository() throws Exception {
                JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
                jobRepositoryFactoryBean.setDataSource(dataSource);
                jobRepositoryFactoryBean
                        .setSerializer(executionContextSerializer);
                jobRepositoryFactoryBean.setTransactionManager(transactionManager);
                jobRepositoryFactoryBean.setIsolationLevelForCreate("ISOLATION_READ_COMMITTED");
                jobRepositoryFactoryBean.afterPropertiesSet();
                return jobRepositoryFactoryBean.getObject();
            }
        };
    }

回答1

不仅仅是一个解决方案,我还找到了一种解决方法。由于只需要序列化,我删除了 BatchConfigurer 并向 DTO 添加了以下注释:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)

相似文章