2015-11-02 43 views
0

我有一個DAO類來從Hibernate檢索一組數據。CustomItemReader從DAO檢索列表

<batch:step id="firstStep"> 
     <batch:tasklet> 
      <batch:chunk reader="firstReader" writer="firstWriter" 
       processor="itemProcessor" commit-interval="2"> 
      </batch:chunk> 
     </batch:tasklet> 
    </batch:step> 

<bean id="firstReader" class="com.process.MyReader" 
    scope="step"> 
</bean> 

在我的閱讀器裏面,我會打電話給DAO來讀取數據。

public class MyReader implements ItemReader<JobInstance>{ 

private List<JobInstance> jobList; 
private String currentDate; 
@Autowired 
private JobDAO perDAO; 

@BeforeRead 
public void init() { 
    //jobList= perDAO.getPersonAJobList(currentDate); 
} 

@Override 
public JobInstance read() throws Exception, UnexpectedInputException, 
     ParseException, NonTransientResourceException { 
    return !jobList.isEmpty() ? jobList.remove(0) : null; 
} 

@Value("#{jobParameters['currentDate']}") 
public void setCurrentDate(String currentDate) { 
    this.currentDate = currentDate; 
} 

@Override 
public void beforeStep(StepExecution stepExecution) { 
    // TODO Auto-generated method stub 
} 

@Override 
public ExitStatus afterStep(StepExecution stepExecution) { 
    // TODO Auto-generated method stub 
    return null; 
} 

}

當我運行的批處理作業,批處理作業一直在重複讀取和處理。

[org.springframework.batch.repeat.support.RepeatTemplate] [getNextResult] [372] - Repeat operation about to start at count=1 

下面是我的DAO類

@Autowired 
private QueryManager queryManager; 

@Autowired 
public JobDAO Impl(SessionFactory sessionFactory) { 
    super(sessionFactory, JobInstance.class); 
} 

public List<JobInstance> getPersonAJobList(String currentDate) { 
    String sql = queryManager.getNamedQuery("getJobList"); 
    System.out.println("---------------------- " + sql + " " + currentDate); 
    SQLQuery query = this.getCurrentSession().createSQLQuery(sql); 
    query.setParameter("current_date", currentDate); 
    .... 
    return result; 
} 

回答

0

如果您填寫的@BeforeRead註釋方法中的列表,該列表將被更新之前,每次讀

看到http://docs.spring.io/spring-batch/apidocs/org/springframework/batch/core/annotation/BeforeRead.html

Marks a method to be called before an item is read from an ItemReader 

如果您需要從DAO獲取項目,則需要考慮實現任

  • 簡單的方法entation - 保持目前的實現,但添加在BeforeRead檢查,以初始化列表中只有一次
  • 有狀態DAO曾經充滿列表,並消除了對每 讀取調用項目
  • 與分頁

更好的辦法是將數據訪問(在SQL)進入批量無國籍DAO,Spring Batch的提供開箱讀者SQL,Hibernate和更...查看http://docs.spring.io/spring-batch/reference/html/listOfReadersAndWriters.html

+0

如果我把這個jobList = perDAO.getPersonAJobList(currentDate);在beforeStep方法裏面,我在這樣的線程錯誤中沒有session。 –

+0

我幾乎可以肯定你沒有交易,因此沒有會​​話BeforeStep,使用BeforeRead有什麼問題? –

+0

正如你所解釋的,dao將在每次閱讀時被調用,所以我打算在beforeStep中放置它,但是我在這種線程錯誤中觸發了沒有session。但是當我在BeforeRead中做到這一點時,我沒有遇到任何問題,只是會繼續循環。如何將transactionManager注入BeforeStep?我已經定義了事務和sessionfactory bean。 –

0

init方法只能調用一次。這樣做的正確方法是實現InitializingBean接口並實現afterPropertiesSet方法,或使用@PostConstruct註釋而不是@BeforeRead。

@BeforeRead的使用肯定是錯誤的,沒有任何意義。

正如邁克爾答案的評論中所提到的,您還應該考慮使用標準讀取器之一從數據庫獲取數據。如果你從getPersonAJobList中獲得幾百或幾千條條目,這不會是一個問題,但是如果你得到了數百萬條目,那肯定是錯誤的做法。

+0

得到一些約束必須使用道檢索。如果我把@PostConstruct或者實現了afterPropertiesSet,我會觸發調用init方法失敗;嵌套異常是java.lang.NullPointerException錯誤。不知道它是我的queryManager返回null –

+0

爲什麼你得到一個NPE? currentDate是否爲空?如果是,那麼你的問題在於使用'@Value'。注意:如果使用'@Value'mit SPEL-Expressions,則需要將org.springframework.context.support.PropertySourcesPlaceholderConfigurer實例化爲Bean。您需要在配置中使用。否則,「@Value」將不起作用。 –

+0

如果我運行if(jobList == null)jobList = perDAO.getPersonAJobList(currentDate);在BeforeRead內部,作業可以完成而不會出錯。所以,它應該能夠獲得價值。 –

0

如何在讀者中添加一個'init'標誌?到MyReader.read()

  1. 如果標誌沒有設置好的電話jobDAO填補jobList並設置標誌
  2. 如果標誌被設置好的消耗jobList項目。

請小心使用jobList.remove(0),因爲您的閱讀器似乎不可重新啓動;您需要將上次使用的項目索引保存到執行上下文中,以便重新啓動將從最後一個未提交的塊的第一項繼續。