1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.springframework.batch.item.database;
17
18 import java.sql.SQLException;
19 import java.util.List;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.springframework.batch.item.ItemWriter;
24 import org.springframework.beans.factory.InitializingBean;
25 import org.springframework.dao.EmptyResultDataAccessException;
26 import org.springframework.dao.InvalidDataAccessResourceUsageException;
27 import org.springframework.orm.ibatis.SqlMapClientCallback;
28 import org.springframework.orm.ibatis.SqlMapClientTemplate;
29 import org.springframework.util.Assert;
30
31 import com.ibatis.sqlmap.client.SqlMapClient;
32 import com.ibatis.sqlmap.client.SqlMapExecutor;
33 import com.ibatis.sqlmap.engine.execution.BatchException;
34 import com.ibatis.sqlmap.engine.execution.BatchResult;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class IbatisBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
53
54 protected static final Log logger = LogFactory.getLog(IbatisBatchItemWriter.class);
55
56 private SqlMapClientTemplate sqlMapClientTemplate;
57
58 private String statementId;
59
60 private boolean assertUpdates = true;
61
62
63
64
65
66
67
68 public void setAssertUpdates(boolean assertUpdates) {
69 this.assertUpdates = assertUpdates;
70 }
71
72
73
74
75
76
77 public void setSqlMapClient(SqlMapClient sqlMapClient) {
78 if (sqlMapClientTemplate == null) {
79 this.sqlMapClientTemplate = new SqlMapClientTemplate(sqlMapClient);
80 }
81 }
82
83
84
85
86
87
88 public void setSqlMapClientTemplate(SqlMapClientTemplate sqlMapClientTemplate) {
89 this.sqlMapClientTemplate = sqlMapClientTemplate;
90 }
91
92
93
94
95
96
97
98 public void setStatementId(String statementId) {
99 this.statementId = statementId;
100 }
101
102
103
104
105 @Override
106 public void afterPropertiesSet() {
107 Assert.notNull(sqlMapClientTemplate, "A SqlMapClient or a SqlMapClientTemplate is required.");
108 Assert.notNull(statementId, "A statementId is required.");
109 }
110
111
112
113
114 @Override
115 public void write(final List<? extends T> items) {
116
117 if (!items.isEmpty()) {
118
119 if (logger.isDebugEnabled()) {
120 logger.debug("Executing batch with " + items.size() + " items.");
121 }
122
123 @SuppressWarnings("unchecked")
124 List<BatchResult> results = (List<BatchResult>) sqlMapClientTemplate.execute(
125 new SqlMapClientCallback() {
126 @Override
127 public Object doInSqlMapClient(SqlMapExecutor executor)
128 throws SQLException {
129 executor.startBatch();
130 for (T item : items) {
131 executor.update(statementId, item);
132 }
133 try {
134 return executor.executeBatchDetailed();
135 } catch (BatchException e) {
136 throw e.getBatchUpdateException();
137 }
138 }
139 });
140
141 if (assertUpdates) {
142 if (results.size() != 1) {
143 throw new InvalidDataAccessResourceUsageException("Batch execution returned invalid results. " +
144 "Expected 1 but number of BatchResult objects returned was " + results.size());
145 }
146
147 int[] updateCounts = results.get(0).getUpdateCounts();
148
149 for (int i = 0; i < updateCounts.length; i++) {
150 int value = updateCounts[i];
151 if (value == 0) {
152 throw new EmptyResultDataAccessException("Item " + i + " of " + updateCounts.length
153 + " did not update any rows: [" + items.get(i) + "]", 1);
154 }
155 }
156 }
157
158 }
159
160 }
161
162 }