我目前正在开发一个处理大型文件文件的应用程序,并使用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());
}
}
答案 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);
}
};
}