我目前正在开发一个应用程序,该应用程序处理一个大文件,并将其存储在带有spring-batch的JPA数据库中。这是应要求进行的。批处理完成后,您可以根据请求使用相同的服务来获取有关加载到数据库中的数据的信息。
单独地,这些请求是有效的,但如果我尝试组合它们,当通过TestEntityManger持久化和刷新数据库中的实体时,我的单元测试会出错。
错误为:
javax.persistence.TransactionRequiredException: no transaction is in progress
批处理完成后,数据库会话似乎没有正确关闭。但这应该由springbatch来处理,但事实并非如此。我的配置有问题吗?还是需要手动关闭会话?如果是,我该怎么做?
我的批处理配置看起来像:
@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());
}
}
由于您使用的是JPA,因此需要使用JpaTransactionManager
,因为默认情况下,Spring Batch将使用DataSourceTransactionManager
(更多详细信息请参阅@EnableBatchProcessing
的javadoc(,它对您的JPA配置一无所知。
您可以使BatchConfiguration
扩展DefaultBatchConfigurer
,或者在上下文中添加BatchConfigurer
类型的bean,并通过重写getTransactionManager
方法指定要使用的JpaTransactionManager
。
下面是一个例子(来自文档(:
@Bean
public BatchConfigurer batchConfigurer(EntityManagerFactory emf) {
return new DefaultBatchConfigurer() {
@Override
public PlatformTransactionManager getTransactionManager() {
return new JpaTransactionManager(emf);
}
};
}