Spring批处理后数据库会话仍然打开 [英] Database session still open after spring batch processing

查看:36
本文介绍了Spring批处理后数据库会话仍然打开的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm currently developing an application that processes a large file file and stores it in a JPA database with spring batch. This happens on request. And after a batch is done you can use the same service to get information about the data loaded in the database on request.

这些请求单独工作,但如果我尝试将它们组合起来,当通过 TestEntityManger 持久化和刷新数据库中的实体时,我的单元测试中会出错.

Separately these requests work, but if I try combining them I get an error in my unit tests when persist and flushing entities in the database via the TestEntityManger.

错误是:

javax.persistence.TransactionRequiredException: no transaction is in progress

批处理完成后,数据库会话似乎没有正确关闭.但这应该由 spring 批处理来处理,但事实并非如此.我的配置有问题还是我需要手动关闭会话?如果是这样,我该怎么做?

It seems like the database session is not properly closed after the batch processing is done. But this should be handled by spring batch, but it isn't. Is there something wrong with my configuration or do I need to manually close the session? And if so, how can I do that?

我的批处理配置如下:

@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();
    }

}

有人可以向我解释我可以做些什么来解决它吗?

Can someone please explain to me what I can do to solve it?

仓库代码:

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());


    }
}

推荐答案

由于你使用的是 JPA,你需要使用 JpaTransactionManager 因为默认情况下,Spring Batch 会使用一个 DataSourceTransactionManager(在 javadoc of @EnableBatchProcessing),它对您的 JPA 配置一无所知.

Since you are using JPA, you need to use the JpaTransactionManager because by default, Spring Batch will use a DataSourceTransactionManager (more details in the javadoc of @EnableBatchProcessing) which knows nothing about your JPA configuration.

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

You can make your BatchConfiguration extend DefaultBatchConfigurer or add a bean of type BatchConfigurer in your context and specify the JpaTransactionManager to use by overriding the getTransactionManager method.

这是一个例子(来自 文档):

Here is an example (from the documentation):

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

这篇关于Spring批处理后数据库会话仍然打开的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆