[SPRING] Spring 배치를 사용한 트랜잭션 관리
SPRINGSpring 배치를 사용한 트랜잭션 관리
실제로 스프링을 발견하고 일부 작업을 설정할 수 있습니다. 이제, 가져온 데이터를 Hibernate / JPA를 사용하여 데이터베이스에 저장하고 싶습니다.이 오류가 계속 발생합니다.
14:46:43.500 [main] ERROR o.s.b.core.step.AbstractStep - Encountered an error executing the step javax.persistence.TransactionRequiredException: no transaction is in progress
문제는 거래와 관련이 있습니다. 엔티티 관리자와 transactionManager에 대한 스프링 자바 설정은 다음과 같다.
@Configuration
public class PersistenceSpringConfig implements EnvironmentAware
{
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws Exception
{
// Initializes the entity manager
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setPersistenceUnitName(PERSISTENCE_UNIT_NAME);
factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
factoryBean.setDataSource(dataSource());
// Scans the database model
factoryBean.setPackagesToScan(EntiteJuridiqueJPA.class.getPackage().getName());
// Defines the Hibernate properties
Properties jpaProperties = new Properties();
jpaProperties.setProperty("hibernate.show_sql", "false");
jpaProperties.setProperty("hibernate.format_sql", "false");
String connectionURL = "jdbc:h2:file:" + getDatabaseLocation();
jpaProperties.setProperty("hibernate.connection.url", connectionURL);
jpaProperties.setProperty("hibernate.connection.username", "sa");
jpaProperties.setProperty("hibernate.connection.driver_class", "org.h2.Driver");
jpaProperties.setProperty("hibernate.dialect", H2Dialect.class.getName());
jpaProperties.setProperty("hibernate.hbm2ddl.auto", "create");
jpaProperties.setProperty("hibernate.hbm2ddl.import_files_sql_extractor", "org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor");
jpaProperties.setProperty("hibernate.hbm2ddl.import_files",
"org/springframework/batch/core/schema-drop-h2.sql,org/springframework/batch/core/schema-h2.sql");
factoryBean.setJpaProperties(jpaProperties);
return factoryBean;
}
@Bean
public PlatformTransactionManager transactionManager2() throws Exception
{
EntityManagerFactory object = entityManagerFactory().getObject();
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(object);
return jpaTransactionManager;
}
JpaItemWriter를 사용하여 데이터베이스에 데이터를 저장합니다.
@Bean
public ItemWriter<EntiteJuridiqueJPA> writer()
{
JpaItemWriter<EntiteJuridiqueJPA> writer = new JpaItemWriter<EntiteJuridiqueJPA>();
writer.setEntityManagerFactory(entityManagerFactory.getObject());
return writer;
}
이것은 예외를 발생시키는 코드입니다. javax.persistence.TransactionRequiredException : 트랜잭션이 진행되고 있지 않습니다.
이 문제를 해결하는 방법에 대한 아이디어?
[편집] 저는 작업 정의와 단계 정의도 넣습니다. 모든 Spring 설정은 Java로 작성됩니다.
@Configuration
@EnableBatchProcessing
@Import(PersistenceSpringConfig.class)
public class BatchSpringConfig
{
@Autowired
private JobBuilderFactory jobBuilders;
@Autowired
private StepBuilderFactory stepBuilders;
@Autowired
private DataSource dataSource;
@Autowired
private LocalContainerEntityManagerFactoryBean entityManagerFactory;
@Bean
public Step step()
{
return stepBuilders.get("step").<EntiteJuridique, EntiteJuridiqueJPA> chunk(5).reader(cvsReader(null))
.processor(processor()).writer(writer()).listener(processListener()).build();
}
@Bean
@StepScope
public FlatFileItemReader<EntiteJuridique> cvsReader(@Value("#{jobParameters[input]}") String input)
{
FlatFileItemReader<EntiteJuridique> flatFileReader = new FlatFileItemReader<EntiteJuridique>();
flatFileReader.setLineMapper(lineMapper());
flatFileReader.setResource(new ClassPathResource(input));
return flatFileReader;
}
@Bean
public LineMapper<EntiteJuridique> lineMapper()
{
DefaultLineMapper<EntiteJuridique> lineMapper = new DefaultLineMapper<EntiteJuridique>();
DelimitedLineTokenizer lineTokenizer = new DelimitedLineTokenizer();
lineTokenizer.setDelimiter(";");
lineTokenizer.setNames(new String[] { "MEGA_ENTITE", "PORTEFEUILLE", "MEGA_ENTITE", "Libellé" });
BeanWrapperFieldSetMapper<EntiteJuridique> fieldSetMapper = new BeanWrapperFieldSetMapper<EntiteJuridique>();
fieldSetMapper.setTargetType(EntiteJuridique.class);
lineMapper.setLineTokenizer(lineTokenizer);
lineMapper.setFieldSetMapper(fieldSetMapper);
return lineMapper;
}
@Bean
public Job dataInitializer()
{
return jobBuilders.get("dataInitializer").listener(protocolListener()).start(step()).build();
}
@Bean
public ItemProcessor<EntiteJuridique, EntiteJuridiqueJPA> processor()
{
return new EntiteJuridiqueProcessor();
}
@Bean
public ItemWriter<EntiteJuridiqueJPA> writer()
{
JpaItemWriter<EntiteJuridiqueJPA> writer = new JpaItemWriter<EntiteJuridiqueJPA>();
writer.setEntityManagerFactory(entityManagerFactory.getObject());
return writer;
// return new EntiteJuridiqueWriter();
}
@Bean
public ProtocolListener protocolListener()
{
return new ProtocolListener();
}
@Bean
public CSVProcessListener processListener()
{
return new CSVProcessListener();
}
@Bean
public PlatformTransactionManager transactionManager2() throws Exception
{
EntityManagerFactory object = entityManagerFactory.getObject();
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager(object);
return jpaTransactionManager;
}
[편집] 나는 아직도이 문제에 붙어있다. stepBuilders에 대한 트랜잭션 관리자를 설정하여 @Sean Patrick Floyd 및 @bellabax 제안을 따라했지만 여전히 동일한 예외가 발생합니다. 나는 스프링 배치의 entityManager를 독립적으로 테스트했으며 데이터베이스에 모든 데이터를 저장할 수 있습니다.
그러나 Spring 배치와 동일한 엔티티 관리자를 사용할 때이 예외가 있습니다.
누구든지 봄 배치 내에서 트랜잭션을 관리하는 방법에 대해 더 많은 통찰력을 줄 수 있습니까? 너 도움을 청해?
해결법
-
==============================
1.문제는 두 번째 트랜잭션 관리자 (transactionManager2)를 생성하지만 Spring Batch는 다른 트랜잭션 관리자를 사용하여 트랜잭션을 시작한다는 것입니다. @EnableBatchProcessing을 사용하면 Spring Batch는 트랜잭션에 사용할 트랜잭션 관리자를 자동으로 등록하고 JpaTransactionManager는 결코 사용되지 않습니다. Spring Batch가 트랜잭션에 사용하는 트랜잭션 관리자를 변경하려면 BatchConfigurer 인터페이스를 구현해야한다. 이 예제를 보자 : https://github.com/codecentric/spring-batch-javaconfig/blob/master/src/main/java/de/codecentric/batch/configuration/WebsphereInfrastructureConfiguration.java. 여기서는 트랜잭션 관리자를 WebspherUowTransactionManager로 전환하는 것과 같은 방법으로 트랜잭션 관리자를 다른 트랜잭션 관리자로 전환 할 수 있습니다. 다음을 설명하는 블로그 게시물에 대한 링크가 있습니다. http://blog.codecentric.de/ko/2013/06/spring-batch-2-2-javaconfig-part-3-profiles-and-environments/
문제는 두 번째 트랜잭션 관리자 (transactionManager2)를 생성하지만 Spring Batch는 다른 트랜잭션 관리자를 사용하여 트랜잭션을 시작한다는 것입니다. @EnableBatchProcessing을 사용하면 Spring Batch는 트랜잭션에 사용할 트랜잭션 관리자를 자동으로 등록하고 JpaTransactionManager는 결코 사용되지 않습니다. Spring Batch가 트랜잭션에 사용하는 트랜잭션 관리자를 변경하려면 BatchConfigurer 인터페이스를 구현해야한다. 이 예제를 보자 : https://github.com/codecentric/spring-batch-javaconfig/blob/master/src/main/java/de/codecentric/batch/configuration/WebsphereInfrastructureConfiguration.java. 여기서는 트랜잭션 관리자를 WebspherUowTransactionManager로 전환하는 것과 같은 방법으로 트랜잭션 관리자를 다른 트랜잭션 관리자로 전환 할 수 있습니다. 다음을 설명하는 블로그 게시물에 대한 링크가 있습니다. http://blog.codecentric.de/ko/2013/06/spring-batch-2-2-javaconfig-part-3-profiles-and-environments/
-
==============================
2.단계 정의에서 트랜잭션 관리자를 명시 적으로 참조해야합니다.
단계 정의에서 트랜잭션 관리자를 명시 적으로 참조해야합니다.
<job id="sampleJob" job-repository="jobRepository"> <step id="step1"> <tasklet transaction-manager="transactionManager"> <chunk reader="itemReader" writer="itemWriter" commit-interval="10"/> </tasklet> </step> </job>
참조 : 5.1.1. 단계 구성
아, JavaConfig를 사용하는 것으로 확인되면 builder.transactionManager (transactionManager) (StepBuilderHelper에서 상속)를 사용하여 TaskletStepBuilder에 트랜잭션 관리자를 지정해야합니다.
from https://stackoverflow.com/questions/17947970/transaction-management-with-spring-batch by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Vaadin : 위젯 세트가로드되지 않습니다. (0) | 2019.05.27 |
---|---|
[SPRING] 배치에서 내 데이터 소스를 사용하지 않는 스프링 배치 프로젝트를 만들고 싶습니다. (0) | 2019.05.27 |
[SPRING] 혼합 매개 변수 전략 - 명명 된, 위치 또는 JPA 순서 전략 중 하나만 사용 (0) | 2019.05.27 |
[SPRING] p6Spy로 작업 할 수 없습니다. (0) | 2019.05.27 |
[SPRING] 스프링 부트 : accessDeniedHandler가 작동하지 않습니다. (0) | 2019.05.27 |