1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.spring.batch;
17
18 import static org.springframework.util.Assert.isTrue;
19 import static org.springframework.util.Assert.notNull;
20
21 import java.util.List;
22
23 import org.apache.ibatis.executor.BatchResult;
24 import org.apache.ibatis.logging.Log;
25 import org.apache.ibatis.logging.LogFactory;
26 import org.apache.ibatis.session.ExecutorType;
27 import org.apache.ibatis.session.SqlSessionFactory;
28 import org.mybatis.spring.SqlSessionTemplate;
29 import org.springframework.batch.item.ItemWriter;
30 import org.springframework.beans.factory.InitializingBean;
31 import org.springframework.dao.EmptyResultDataAccessException;
32 import org.springframework.dao.InvalidDataAccessResourceUsageException;
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class MyBatisBatchItemWriter<T> implements ItemWriter<T>, InitializingBean {
56
57 private static final Log LOGGER = LogFactory.getLog(MyBatisBatchItemWriter.class);
58
59 private SqlSessionTemplate sqlSessionTemplate;
60
61 private String statementId;
62
63 private boolean assertUpdates = true;
64
65
66
67
68
69
70
71 public void setAssertUpdates(boolean assertUpdates) {
72 this.assertUpdates = assertUpdates;
73 }
74
75
76
77
78
79
80 public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
81 if (sqlSessionTemplate == null) {
82 this.sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory, ExecutorType.BATCH);
83 }
84 }
85
86
87
88
89
90
91 public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
92 this.sqlSessionTemplate = sqlSessionTemplate;
93 }
94
95
96
97
98
99
100
101 public void setStatementId(String statementId) {
102 this.statementId = statementId;
103 }
104
105
106
107
108 @Override
109 public void afterPropertiesSet() {
110 notNull(sqlSessionTemplate, "A SqlSessionFactory or a SqlSessionTemplate is required.");
111 isTrue(ExecutorType.BATCH == sqlSessionTemplate.getExecutorType(), "SqlSessionTemplate's executor type must be BATCH");
112 notNull(statementId, "A statementId is required.");
113 }
114
115
116
117
118 @Override
119 public void write(final List<? extends T> items) {
120
121 if (!items.isEmpty()) {
122
123 if (LOGGER.isDebugEnabled()) {
124 LOGGER.debug("Executing batch with " + items.size() + " items.");
125 }
126
127 for (T item : items) {
128 sqlSessionTemplate.update(statementId, item);
129 }
130
131 List<BatchResult> results = sqlSessionTemplate.flushStatements();
132
133 if (assertUpdates) {
134 if (results.size() != 1) {
135 throw new InvalidDataAccessResourceUsageException("Batch execution returned invalid results. " +
136 "Expected 1 but number of BatchResult objects returned was " + results.size());
137 }
138
139 int[] updateCounts = results.get(0).getUpdateCounts();
140
141 for (int i = 0; i < updateCounts.length; i++) {
142 int value = updateCounts[i];
143 if (value == 0) {
144 throw new EmptyResultDataAccessException("Item " + i + " of " + updateCounts.length
145 + " did not update any rows: [" + items.get(i) + "]", 1);
146 }
147 }
148 }
149 }
150 }
151
152 }