2013-07-30 159 views
4

我发现实际上Spring和我能够设置一些工作。现在,我想救我的进口DATAS中使用Hibernate/JPA和我不断收到此错误数据库:用Spring批处理事务管理

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的Spring Java配置和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到DATAS存储在数据库中:

@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; 
    } 

[编辑]我还是坚持了这个问题。我通过设置stepBuilders的事务管理器来遵循@Sean Patrick Floyd和@bellabax的建议,但我仍然得到相同的异常。我已经独立测试了我的entityManager,并且能够将任何数据存储在数据库中。

但是,当与spring批处理使用相同的实体管理器时,我有这个异常。

任何人都可以提供更多见解如何在春季批次内管理交易? 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

好吧thx托比亚斯,我没有注意到你的教程的一部分。 Thx为您的答案。 – Dimitri

+1

使用Spring 4,该解决方案不能按原样工作,批处理将在主数据源中创建它的模式,这很烦人,并且在第一次运行后,每次都会出现重复主键错误。另外,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

我还有另外一个问题,你认为Spring批处理中使用的Transaction将会/必须和Jpa中的一样吗?正如你在我的代码中看到的,编写者正在使用JpaWriter来传递一个entityManagerFactory。我认为这是问题。我正在存储数据,但没有绑定到此jpa实例的事务。你怎么看? – Dimitri