在春季批处理之后,数据库会话仍然打开

时间:2018-12-07 10:57:25

标签: spring spring-data-jpa spring-batch

我目前正在开发一个处理大型文件文件的应用程序,并使用spring batch将其存储在JPA数据库中。这是根据要求发生的。批处理完成后,您可以使用同一服务来获取有关应要求在数据库中加载的数据的信息。

这些请求单独起作用,但是如果我尝试将它们组合在一起,则当持久化并通过TestEntityManger刷新数据库中的实体时,在单元测试中会出现错误。

错误是:

javax.persistence.TransactionRequiredException: no transaction is in progress

似乎在完成批处理后,数据库会话未正确关闭。但这应该由春季批处理,但事实并非如此。我的配置有问题吗?还是需要手动关闭会话?如果是这样,我该怎么办?

我的批处理配置如下:

@Configuration
@EnableBatchProcessing
public class BatchConfiguration {

    @Autowired
    public JobBuilderFactory jobBuilderFactory;

    @Autowired
    public StepBuilderFactory stepBuilderFactory;

    @Autowired
    public CustomerRepository customerRepository;

    @Bean
    public JsonItemReader<Klant> jsonItemReader() {
        return new JsonItemReaderBuilder<Klant>()
                .jsonObjectReader(new JacksonJsonObjectReader<>    (Klant.class))
                .resource(new ClassPathResource("sample-data.json"))
                .name("tradeJsonItemReader")
                .build();
    }

    @Bean
    public KlantItemProcessor processor() {
        return new KlantItemProcessor();
    }

   @Bean
    public RepositoryItemWriter<Customer> writer(){
        return new RepositoryItemWriterBuilder<Customer>()
                .methodName("save")
                .repository(customerRepository)
                .build();
    }

    @Bean
    public Job importUserJob(JobCompletionNotificationListener listener, Step step1) {
        return jobBuilderFactory.get("importUserJob")
                .incrementer(new RunIdIncrementer())
                .listener(listener)
                .flow(step1)
                .end()
                .build();
    }

    @Bean
    public Step step1(RepositoryItemWriter<Customer> writer) {
        return stepBuilderFactory.get("step1")
                .<Klant, Customer> chunk(1)
                .reader(jsonItemReader())
                .processor(processor())
                .writer(writer)
                .build();
    }

}

有人可以向我解释解决该问题的方法吗?

存储库代码:

public interface CustomerRepository extends 
PagingAndSortingRepository<Customer, String> {

    Optional<Customer> findCustomerByCustomerProspectNumber(int customerProspectNumber);

}

单元测试:

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@DataJpaTest
@Import({SecurityAutoConfiguration.class})
public abstract class BaseAccountRepositoryTest {

    private static final String[] DATA = {
            "/backend/model/exampleCustomer.json"
    };

    @Autowired
    protected TestEntityManager em;

    @Autowired
    protected CustomerRepository customerRepository;

    @Autowired
    protected TransactionRepository transactionRepository;

    @Autowired
    protected AccountRepository accountRepository;


    @Before
    public void init(){
        List<Customer> customersList = GsonUtil.fromJson(Customer.class, DATA);
        customersList.forEach(customer -> {

            em.persistAndFlush(customer);

            customer.getAccounts().forEach(account -> {
                account.setCustomer(customer);
                em.persistAndFlush(account);

                account.getTransactions().forEach(transaction -> {
                    transaction.setAccount(account);
                    em.persistAndFlush(transaction);
                });
            });
        });

        assertEquals(DATA.length, customerRepository.count());
        assertEquals(1, transactionRepository.count());
        assertEquals(1, accountRepository.count());


    }
}

1 个答案:

答案 0 :(得分:1)

由于您使用的是JPA,因此您需要使用JpaTransactionManager,因为默认情况下,Spring Batch将使用DataSourceTransactionManager(更多信息在@EnableBatchProcessing的{​​{3}}中)对您的JPA配置一无所知。

您可以使BatchConfiguration扩展DefaultBatchConfigurer或在上下文中添加类型BatchConfigurer的bean,并通过覆盖JpaTransactionManager指定要使用的getTransactionManager方法。

以下是一个示例(来自javadoc):

@Bean
public BatchConfigurer batchConfigurer(EntityManagerFactory emf) {
    return new DefaultBatchConfigurer() {
        @Override
        public PlatformTransactionManager getTransactionManager() {
            return new JpaTransactionManager(emf);
        }
    };
}