Сессия базы данных все еще открыта после весенней пакетной обработки - PullRequest
0 голосов
/ 07 декабря 2018

В настоящее время я разрабатываю приложение, которое обрабатывает большой файл и сохраняет его в базе данных JPA с помощью Spring Batch.Это происходит по запросу.И после того, как пакет сделан, вы можете использовать тот же сервис, чтобы получить информацию о данных, загруженных в базу данных по запросу.

Отдельно эти запросы работают, но если я пытаюсь объединить их, я получаю ошибку в своих модульных тестах при сохранении и сбрасывании сущностей в базе данных через 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 голосов
/ 07 декабря 2018

Поскольку вы используете JPA, вам нужно использовать JpaTransactionManager, потому что по умолчанию Spring Batch будет использовать DataSourceTransactionManager (подробности в javadoc из @EnableBatchProcessing), который ничего не знает оваша конфигурация JPA.

Вы можете сделать свой BatchConfiguration расширенный DefaultBatchConfigurer или добавить bean-компонент типа BatchConfigurer в своем контексте и указать JpaTransactionManager для использования, переопределив метод getTransactionManager.

Вот пример (из документации ):

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