1 | package org.springframework.batch.item.database.support; |
2 | |
3 | import java.util.List; |
4 | |
5 | import org.springframework.batch.item.ExecutionContext; |
6 | import org.springframework.batch.item.ExecutionContextUserSupport; |
7 | import org.springframework.batch.item.database.DrivingQueryItemReader; |
8 | import org.springframework.batch.item.database.KeyCollector; |
9 | import org.springframework.orm.ibatis.SqlMapClientTemplate; |
10 | import org.springframework.util.Assert; |
11 | import org.springframework.util.ClassUtils; |
12 | |
13 | import com.ibatis.sqlmap.client.SqlMapClient; |
14 | |
15 | /** |
16 | * {@link KeyCollector} based on iBATIS ORM framework. It is functionally |
17 | * similar to {@link SingleColumnJdbcKeyCollector} but does not make assumptions |
18 | * about the primary key structure. A separate restart query is necessary to |
19 | * ensure that only the required keys remaining for processing are returned, rather |
20 | * than the entire original list.</p> |
21 | * |
22 | * @author Robert Kasanicky |
23 | * @author Lucas Ward |
24 | * @see DrivingQueryItemReader |
25 | */ |
26 | public class IbatisKeyCollector extends ExecutionContextUserSupport implements KeyCollector { |
27 | |
28 | private static final String RESTART_KEY = "key.index"; |
29 | |
30 | private SqlMapClientTemplate sqlMapClientTemplate; |
31 | |
32 | private String drivingQuery; |
33 | |
34 | private String restartQueryId; |
35 | |
36 | public IbatisKeyCollector() { |
37 | setName(ClassUtils.getShortName(IbatisKeyCollector.class)); |
38 | } |
39 | |
40 | /* |
41 | * Retrieve the keys using the provided driving query id. |
42 | * |
43 | * @see KeyCollector#retrieveKeys() |
44 | */ |
45 | public List retrieveKeys(ExecutionContext executionContext) { |
46 | if (executionContext.containsKey(getKey(RESTART_KEY))) { |
47 | Object key = executionContext.get(getKey(RESTART_KEY)); |
48 | return sqlMapClientTemplate.queryForList(restartQueryId, key); |
49 | } |
50 | else { |
51 | return sqlMapClientTemplate.queryForList(drivingQuery); |
52 | } |
53 | } |
54 | |
55 | /* |
56 | * (non-Javadoc) |
57 | * @see KeyCollector#saveState(Object, ExecutionContext) |
58 | */ |
59 | public void updateContext(Object key, ExecutionContext executionContext) { |
60 | Assert.notNull(key, "Key must not be null"); |
61 | Assert.notNull(executionContext, "ExecutionContext must be null"); |
62 | executionContext.put(getKey(RESTART_KEY), key); |
63 | } |
64 | |
65 | /* |
66 | * (non-Javadoc) |
67 | * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() |
68 | */ |
69 | public void afterPropertiesSet() throws Exception { |
70 | Assert.notNull(sqlMapClientTemplate, "SqlMaperClientTemplate must not be null."); |
71 | Assert.hasText(drivingQuery, "The DrivingQuery must not be null or empty."); |
72 | } |
73 | |
74 | /** |
75 | * @param sqlMapClient configured iBATIS client |
76 | */ |
77 | public void setSqlMapClient(SqlMapClient sqlMapClient) { |
78 | this.sqlMapClientTemplate = new SqlMapClientTemplate(); |
79 | this.sqlMapClientTemplate.setSqlMapClient(sqlMapClient); |
80 | } |
81 | |
82 | /** |
83 | * @param drivingQueryId id of the iBATIS select statement that will be used |
84 | * to retrieve the list of primary keys |
85 | */ |
86 | public void setDrivingQueryId(String drivingQueryId) { |
87 | this.drivingQuery = drivingQueryId; |
88 | } |
89 | |
90 | /** |
91 | * Set the id of the restart query. |
92 | * |
93 | * @param restartQueryId id of the iBatis select statement that will be used |
94 | * to retrieve the list of primary keys after a restart. |
95 | */ |
96 | public void setRestartQueryId(String restartQueryId) { |
97 | this.restartQueryId = restartQueryId; |
98 | } |
99 | |
100 | public final SqlMapClientTemplate getSqlMapClientTemplate() { |
101 | return sqlMapClientTemplate; |
102 | } |
103 | |
104 | } |