Spring批处理后数据库会话仍然打开 [英] Database session still open after spring batch processing
问题描述
我目前正在开发一个应用程序,它处理一个大文件并将其存储在带有 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屋!