2014-03-19 139 views
2

我想使用JpaItemWriter批量持久實體。但是,當我使用下面的代碼要堅持,我被告知:JpaItemWriter:沒有交易正在進行中

@Bean 
public ItemWriter<T> writer() { 
    JpaItemWriter<T> itemWriter = new JpaItemWriter<>(); 
    itemWriter.setEntityManagerFactory(emf); 
} 

@Configuration 
@EnableTransactionManagement 
@EnableBatchProcessing 
class Config{ { 
    @Bean 
    public LocalContainerEntityManagerFactoryBean emf() { 
     LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); 
     emf.setDataSource(dataSource()); 
     emf.setPackagesToScan("my.package"); 
     emf.setJpaVendorAdapter(jpaAdapter()); 
     emf.setJpaProperties(jpaProterties()); 
     return emf; 
} 

編輯:

@Bean 
public Job airlineJob(JobBuilderFactory jobs, Step step) { 
    return jobs.get("job") 
      .start(step) 
      .build(); 
} 

//Reader is a `FlatFileItemReader`, writer is `CustomItemWriter`. 
@Bean 
public Step step(StepBuilderFactory steps, 
     MultiResourceItemReader<T> rea, 
     ItemProcessor<T, T> pro, 
     ItemWriter<T> wr) { 
    return steps.get("step") 
      .reader(rea) 
      .processor(proc) 
      .writer(wr) 
      .build(); 
} 

//use same datasource and tx manager as in the full web application 
@Bean 
public JobLauncher launcher(TransactionManager tx, DataSource ds) throws Exception { 
    SimpleJobLauncher launcher = new SimpleJobLauncher(); 

    JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); 
    factory.setDataSource(ds); 
    factory.setTransactionManager(tx); 

    jobLauncher.setJobRepository(factory.getJobRepository()); 
    return launcher; 
} 

Hibernate: 
    select 
     nextval ('hibernate_sequence') 
[] 2014-03-19 15:46:02,237 ERROR : TransactionRequiredException: no transaction is in progress 

我怎樣才能在以下交易啓用編輯2作爲對@Haim的迴應:

@Bean 
    public JpaItemWriter<T> jpaItemWriter(EntityManagerFactory emf) { 
     JpaItemWriter<T> writer = new JpaItemWriter<T>(); 
     writer.setEntityManagerFactory(emf); 
     return writer; 
    } 
+0

你爲什麼要構建一個JpaItemWriter?那應該在春季完成?如果沒有進行中的交易,這意味着您沒有正確設置Spring Batch。添加相關的配置和類。 –

+0

因爲批處理過程需要將讀者和寫者定義爲Bean。 'stepBuilderFactory.get(「step」)。reader(reader).writer(writer).build();' – membersound

+0

你是否正在使用Spring Batch 3和Java Config方法。對於初學者來說,你不應該調用'afterPropertiesSet'的spring會爲你做這件事(它只是一個像其他bean一樣的bean)。但請仍然添加您的實際Spring批處理和事務配置。我希望你也有一個'JpaTransactionManager'和一些'@ EnableTransactionManagement'。 –

回答

5

我同意邁克爾·米內拉:春季批處理作業庫不喜歡與他人分享它的事務管理器。邏輯很簡單,如果您在步驟失敗時與步驟事務管理器共享作業事務管理器,它將回滾寫入作業存儲庫的步驟和數據。這意味着您不會爲重新啓動作業而保留數據。 爲了使用兩個事務管理器,你需要:

的情況下,刪除@EnableTransactionManagement你使用它爲@Transactional上述
定義一個額外的事務管理器

@Bean 
@Qualifier("jpaTrx") 
public PlatformTransactionManager jpaTransactionManager() { 
     return new JpaTransactionManager(emf()); 
} 

設置事務經理到你的腳步

@Autowired 
@Qualifier("jpaTrx") 
PlatformTransactionManager jpaTransactionManager 

//Reader is a FlatFileItemReader, writer is CustomItemWriter. 
    @Bean 
    public Step step(StepBuilderFactory steps, 
      MultiResourceItemReader<T> rea, 
      ItemProcessor<T, T> pro, 
      ItemWriter<T> wr) { 
     return steps.get("step") 
       //attach tx manager 
       .transactionManager(jpaTransactionManager) 
       .reader(rea) 
       .processor(proc) 
       .writer(wr) 
       .build(); 
    } 
+0

感謝您的回答。使用獨立的entitymanger可以使用你的方法。但是Spring會抱怨'JpaItemWriter'沒有定義'EntityManager'。所以我創建了一個'@ Bean',在那裏我使用'new'運算符創建'JpaItemWriter',並通過注入來設置emf(請參閱我上面編輯的問題)。它是否正確? – membersound

+1

這很好。這取決於您添加事務管理器配置的位置。在我的例子中,我假設所有人都被安排在同一個班上。我希望將事務管理器放在與emf相同的文件中,並在第二個配置文件中注入它。看到我的更新 –

0

我解決它創造我自己的事務JpaWriter:

@Component 
public class CustomItemWriter<T> extends JpaItemWriter<T> { 
    @Override 
    @Transactional 
    public void write(List<? extends T> items) { 
     super.write(items); 
    } 
} 
+0

這將無法正常工作。由於Spring Batch內部具有手動事務管理,因此'@ Transactional'會導致Spring Batch出現問題。作爲@ m-deinum請求,如果您有興趣正確解決此問題,請發佈實際批處理作業的配置。 –

+1

嗯,但它的工作。總之看到我的編輯 – membersound

+0

你試過所有的錯誤情況?事務回滾?重試/跳過?在Spring批處理中使用@Transactional存在已知的問題,建議不要使用它。 –