Spring Batch JpaItemWriter против HibernateItemWriter и почему требуется HibernateTransactionManager при использовании HibernateItemWriter

Я работаю над Spring Batch с проектом Spring Boot. Мой вопрос: зачем нужны HibernateTransactionManager и SessionFactory из LocalSessionFactoryBean, когда я использую HibernateItemWriter, как показано ниже?

Application.java

import java.util.Properties;
import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBuilder;
import org.springframework.transaction.PlatformTransactionManager;

@SpringBootApplication
@EnableBatchProcessing
public class Application {

public static void main(String[] args) throws Exception {
    SpringApplication.run(Application.class, args);
}

@Bean
public PlatformTransactionManager transactionManager() {
    HibernateTransactionManager transactionManager = new HibernateTransactionManager();
    transactionManager.setSessionFactory(sessionFactory(null));
    return transactionManager;
}

@Bean
public SessionFactory sessionFactory(DataSource datasource) {
    Properties properties = new Properties();
    properties.setProperty("hibernate.show_sql", "true");
    properties.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");

    return new LocalSessionFactoryBuilder(datasource).scanPackages("hello")
             .addProperties(properties)
            .buildSessionFactory();
}
}

BatchConfiguration.java

import org.hibernate.SessionFactory;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.item.ItemWriter;
import org.springframework.batch.item.database.HibernateItemWriter;
import org.springframework.batch.item.file.FlatFileItemWriter;
import org.springframework.batch.item.file.transform.BeanWrapperFieldExtractor;
import 
org.springframework.batch.item.file.transform.DelimitedLineAggregator;
import org.springframework.batch.item.file.transform.FieldExtractor;
import org.springframework.batch.item.file.transform.LineAggregator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileSystemResource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.web.client.RestTemplate;

@Configuration
public class BatchConfiguration {

@Autowired
public JobBuilderFactory jobBuilderFactory;

@Autowired
public StepBuilderFactory stepBuilderFactory;

@Autowired
public RestTemplate restTemplate;


@Autowired
public PlatformTransactionManager tManager;

@Value("${file.name}")
public String fileName;


@Bean
@StepScope
public RestItemReader reader2() {
    return new RestItemReader(restTemplate);
}

@Bean
public PersonItemProcessor processor() {
    return new PersonItemProcessor();
}

@Bean
public HibernateItemWriter<Person> hibernateWriter(SessionFactory emf) {
    HibernateItemWriter<Person> writer = new HibernateItemWriter<>();
    writer.setSessionFactory(emf);
    return writer;
}


@Bean
public Step step1() {
    return stepBuilderFactory.get("step1")
            .transactionManager(tManager)
        .<KarvyFundInfoModel, Person> chunk(2)
        .reader(reader2())
        .processor(new PersonItemProcessor())
        .writer(hibernateWriter(null))
        .build();
}
}

Это потому, что если бы я его не включил, и получив SessionFactory из EntityManagerFactory, используя код, как показано ниже

EntityManagerFactory.unwarp(SessionFactory.class);

Я получаю сообщение об ошибке «транзакция не выполняется». Однако это не тот случай, когда я использую JpaItemWriter.

Однако, исходя из моего понимания Spring Batch, при обработке фрагментов менеджер транзакций по умолчанию уже предоставляется.

Обязательно ли предоставлять HibernateTransactionManager и SessionFactory из LocalSessionFactoryBean (из спящего режима), чтобы использовать HibernateItemWriter?

И в чем основное различие между JpaItemWriter и HibernateItemWriter? Я уже проводил исследования по этим двум вопросам, Jpa - это спецификация того, как указать сущность и т. д. С использованием способа аннотации, а спящий режим - одна из реализаций Jpa. Тем не менее, я не очень понимаю это. Имеет ли спящий режим больше функций по сравнению с jpa по умолчанию? Например, SearchCriteria и т. д.?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
6
0
5 437
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

why HibernateTransactionManager and SessionFactory from LocalSessionFactoryBean are needed when I use HibernateItemWriter

По умолчанию, если вы предоставляете bean-компонент DataSource, Spring Batch будет использовать DataSourceTransactionManager для управления транзакциями. Этот менеджер транзакций ничего не знает о вашем контексте JPA / Hibernate. Таким образом, HibernateItemWriter, который использует Hibernate Session за сценой, не «знает» о текущей транзакции, управляемой DataSourceTransactionManager. Отсюда ошибка: no transaction is in progress.

HibernateTransactionManager - это то, что заставляет Hibernate Session участвовать в весенних управляемых транзакциях.

what is the main difference between JpaItemWriter and HibernateItemWriter?

JpaItemWriter использует API-интерфейсы JPA (EntityManagerFactory и EntityManager) для записи элементов. Он не использует API-интерфейсы, специфичные для JPA-провайдеров. Это позволяет переключать провайдера JPA без изменения вашего писателя.

HibernateItemWriter с другой стороны использует специальные API-интерфейсы Hibernate (SessionFactory и Session) и относится только к Hibernate. Этот компонент может быть полезен для приложений, использующих спящий режим напрямую, без использования JPA. У вас может быть такой же писатель, но для другого поставщика JPA, такого как OpenJpaItemWriter или EclipseLinkItemWriter, который использует определенные API от этих поставщиков.


NB: Есть вопрос, похожий на этот, я добавляю его сюда для справки: Управление транзакциями с помощью Spring Batch

Хорошее объяснение! Большое спасибо!

AlexZai 21.09.2018 17:37

Другие вопросы по теме