2013-07-30 2 views
4

Я нахожусь на самом деле Spring, и я могу настроить некоторые задания. Теперь я хотел бы сохранить мой импортированные в ДАННЫЕ базе данных, используя Hibernate/JPA, и я получаю эту ошибку:Управление транзакциями с Spring Batch

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 

Я вижу, что проблема с транзакцией. Вот моя весна ява конфигурация для entityManager и 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: no transaction is in progress

Любая идея, как решить эту проблему?

[Изменить] Я помещаю также определение задания и определение шага. Вся моя конфигурация 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; 
    } 

[EDIT] Я до сих пор застрял с этой проблемой. Я следил за предложениями @Sean Patrick Floyd и @bellabax, установив диспетчер транзакций для stepBuilders, но я все равно получаю то же исключение. Я проверил мой entityManager независимо от весенней партии, и я могу хранить любые данные в базе данных.

Но при использовании того же менеджера объектов с весенним пакетом у меня есть это исключение.

Любой может дать больше информации о том, как управлять транзакциями в рамках весенней партии? Thx для вашей помощи?

ответ

9

проблема заключается в том, что вы создаете второй менеджер транзакций (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/en/2013/06/spring-batch-2-2-javaconfig-part-3-profiles-and-environments/

+0

Ok thx Tobias, я не заметил эту часть ваших уроков. Thx для ваших ответов. – Dimitri

+1

Использование Spring 4, это решение не работает так, как есть, пакет будет создавать его схему в Primary DataSource, что раздражает, и после вашего первого запуска он будет терпеть неудачу каждый раз с повторяющимися ошибками первичного ключа. Кроме того, расширен интерфейс интерфейса BatchConfigurer. – AdrianVeidt

3

Вы должны явно указать свой менеджер транзакций в вашем шаге определения:

<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. Configuring a Step


Ах, видя, что вы используете JavaConfig, вам нужно назначить менеджера транзакций TaskletStepBuilder с использованием builder.transactionManager(transactionManager) (унаследовано от StepBuilderHelper)

+0

Привет и THX для вашего ответа. К сожалению, он по-прежнему не работает. У меня все же есть то же исключение. Как вы думаете, у меня есть правильное определение менеджера транзакций? – Dimitri

+0

И у меня есть другой вопрос, вы думаете, что транзакция, используемая в весенней партии, будет/должна быть такой же, как в Jpa?Как вы видите в моем коде, автор использует JpaWriter, где я передаю entityManagerFactory. Я думаю, что это проблема. Я храню данные, но нет никаких транзакций, связанных с этим экземпляром jpa. Как вы думаете? – Dimitri