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.database.DrivingQueryItemReader; |
7 | import org.springframework.batch.item.database.KeyCollector; |
8 | import org.springframework.batch.item.util.ExecutionContextUserSupport; |
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, |
20 | * rather than the entire original list.</p> |
21 | * |
22 | * The writer is thread safe after its properties are set (normal singleton |
23 | * behaviour). |
24 | * |
25 | * @author Robert Kasanicky |
26 | * @author Lucas Ward |
27 | * @see DrivingQueryItemReader |
28 | */ |
29 | public class IbatisKeyCollector extends ExecutionContextUserSupport implements KeyCollector { |
30 | |
31 | private static final String RESTART_KEY = "key.index"; |
32 | |
33 | private SqlMapClientTemplate sqlMapClientTemplate; |
34 | |
35 | private String drivingQuery; |
36 | |
37 | private String restartQueryId; |
38 | |
39 | public IbatisKeyCollector() { |
40 | setName(ClassUtils.getShortName(IbatisKeyCollector.class)); |
41 | } |
42 | |
43 | /* |
44 | * Retrieve the keys using the provided driving query id. |
45 | * |
46 | * @see KeyCollector#retrieveKeys() |
47 | */ |
48 | public List retrieveKeys(ExecutionContext executionContext) { |
49 | if (executionContext.containsKey(getKey(RESTART_KEY))) { |
50 | Object key = executionContext.get(getKey(RESTART_KEY)); |
51 | return sqlMapClientTemplate.queryForList(restartQueryId, key); |
52 | } |
53 | else { |
54 | return sqlMapClientTemplate.queryForList(drivingQuery); |
55 | } |
56 | } |
57 | |
58 | /* |
59 | * (non-Javadoc) |
60 | * |
61 | * @see KeyCollector#saveState(Object, ExecutionContext) |
62 | */ |
63 | public void updateContext(Object key, ExecutionContext executionContext) { |
64 | Assert.notNull(key, "Key must not be null"); |
65 | Assert.notNull(executionContext, "ExecutionContext must be null"); |
66 | executionContext.put(getKey(RESTART_KEY), key); |
67 | } |
68 | |
69 | /* |
70 | * (non-Javadoc) |
71 | * |
72 | * @see |
73 | * org.springframework.beans.factory.InitializingBean#afterPropertiesSet() |
74 | */ |
75 | public void afterPropertiesSet() throws Exception { |
76 | Assert.notNull(sqlMapClientTemplate, "SqlMaperClientTemplate must not be null."); |
77 | Assert.hasText(drivingQuery, "The DrivingQuery must not be null or empty."); |
78 | } |
79 | |
80 | /** |
81 | * @param sqlMapClient configured iBATIS client |
82 | */ |
83 | public void setSqlMapClient(SqlMapClient sqlMapClient) { |
84 | this.sqlMapClientTemplate = new SqlMapClientTemplate(); |
85 | this.sqlMapClientTemplate.setSqlMapClient(sqlMapClient); |
86 | } |
87 | |
88 | /** |
89 | * @param drivingQueryId id of the iBATIS select statement that will be used |
90 | * to retrieve the list of primary keys |
91 | */ |
92 | public void setDrivingQueryId(String drivingQueryId) { |
93 | this.drivingQuery = drivingQueryId; |
94 | } |
95 | |
96 | /** |
97 | * Set the id of the restart query. |
98 | * |
99 | * @param restartQueryId id of the iBatis select statement that will be used |
100 | * to retrieve the list of primary keys after a restart. |
101 | */ |
102 | public void setRestartQueryId(String restartQueryId) { |
103 | this.restartQueryId = restartQueryId; |
104 | } |
105 | |
106 | public final SqlMapClientTemplate getSqlMapClientTemplate() { |
107 | return sqlMapClientTemplate; |
108 | } |
109 | |
110 | } |