1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.session.defaults;
17
18 import java.io.IOException;
19 import java.sql.Connection;
20 import java.sql.SQLException;
21 import java.util.ArrayList;
22 import java.util.HashMap;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.apache.ibatis.binding.BindingException;
27 import org.apache.ibatis.cursor.Cursor;
28 import org.apache.ibatis.exceptions.ExceptionFactory;
29 import org.apache.ibatis.exceptions.TooManyResultsException;
30 import org.apache.ibatis.executor.BatchResult;
31 import org.apache.ibatis.executor.ErrorContext;
32 import org.apache.ibatis.executor.Executor;
33 import org.apache.ibatis.executor.result.DefaultMapResultHandler;
34 import org.apache.ibatis.executor.result.DefaultResultContext;
35 import org.apache.ibatis.mapping.MappedStatement;
36 import org.apache.ibatis.reflection.ParamNameResolver;
37 import org.apache.ibatis.session.Configuration;
38 import org.apache.ibatis.session.ResultHandler;
39 import org.apache.ibatis.session.RowBounds;
40 import org.apache.ibatis.session.SqlSession;
41
42
43
44
45
46
47
48 public class DefaultSqlSession implements SqlSession {
49
50 private final Configuration configuration;
51 private final Executor executor;
52
53 private final boolean autoCommit;
54 private boolean dirty;
55 private List<Cursor<?>> cursorList;
56
57 public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
58 this.configuration = configuration;
59 this.executor = executor;
60 this.dirty = false;
61 this.autoCommit = autoCommit;
62 }
63
64 public DefaultSqlSession(Configuration configuration, Executor executor) {
65 this(configuration, executor, false);
66 }
67
68 @Override
69 public <T> T selectOne(String statement) {
70 return this.selectOne(statement, null);
71 }
72
73 @Override
74 public <T> T selectOne(String statement, Object parameter) {
75
76 List<T> list = this.selectList(statement, parameter);
77 if (list.size() == 1) {
78 return list.get(0);
79 } else if (list.size() > 1) {
80 throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
81 } else {
82 return null;
83 }
84 }
85
86 @Override
87 public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
88 return this.selectMap(statement, null, mapKey, RowBounds.DEFAULT);
89 }
90
91 @Override
92 public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
93 return this.selectMap(statement, parameter, mapKey, RowBounds.DEFAULT);
94 }
95
96 @Override
97 public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
98 final List<? extends V> list = selectList(statement, parameter, rowBounds);
99 final DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler<>(mapKey,
100 configuration.getObjectFactory(), configuration.getObjectWrapperFactory(), configuration.getReflectorFactory());
101 final DefaultResultContext<V> context = new DefaultResultContext<>();
102 for (V o : list) {
103 context.nextResultObject(o);
104 mapResultHandler.handleResult(context);
105 }
106 return mapResultHandler.getMappedResults();
107 }
108
109 @Override
110 public <T> Cursor<T> selectCursor(String statement) {
111 return selectCursor(statement, null);
112 }
113
114 @Override
115 public <T> Cursor<T> selectCursor(String statement, Object parameter) {
116 return selectCursor(statement, parameter, RowBounds.DEFAULT);
117 }
118
119 @Override
120 public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
121 try {
122 MappedStatement ms = configuration.getMappedStatement(statement);
123 Cursor<T> cursor = executor.queryCursor(ms, wrapCollection(parameter), rowBounds);
124 registerCursor(cursor);
125 return cursor;
126 } catch (Exception e) {
127 throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
128 } finally {
129 ErrorContext.instance().reset();
130 }
131 }
132
133 @Override
134 public <E> List<E> selectList(String statement) {
135 return this.selectList(statement, null);
136 }
137
138 @Override
139 public <E> List<E> selectList(String statement, Object parameter) {
140 return this.selectList(statement, parameter, RowBounds.DEFAULT);
141 }
142
143 @Override
144 public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
145 return selectList(statement, parameter, rowBounds, Executor.NO_RESULT_HANDLER);
146 }
147
148 private <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
149 try {
150 MappedStatement ms = configuration.getMappedStatement(statement);
151 return executor.query(ms, wrapCollection(parameter), rowBounds, handler);
152 } catch (Exception e) {
153 throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
154 } finally {
155 ErrorContext.instance().reset();
156 }
157 }
158
159 @Override
160 public void select(String statement, Object parameter, ResultHandler handler) {
161 select(statement, parameter, RowBounds.DEFAULT, handler);
162 }
163
164 @Override
165 public void select(String statement, ResultHandler handler) {
166 select(statement, null, RowBounds.DEFAULT, handler);
167 }
168
169 @Override
170 public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
171 selectList(statement, parameter, rowBounds, handler);
172 }
173
174 @Override
175 public int insert(String statement) {
176 return insert(statement, null);
177 }
178
179 @Override
180 public int insert(String statement, Object parameter) {
181 return update(statement, parameter);
182 }
183
184 @Override
185 public int update(String statement) {
186 return update(statement, null);
187 }
188
189 @Override
190 public int update(String statement, Object parameter) {
191 try {
192 dirty = true;
193 MappedStatement ms = configuration.getMappedStatement(statement);
194 return executor.update(ms, wrapCollection(parameter));
195 } catch (Exception e) {
196 throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e);
197 } finally {
198 ErrorContext.instance().reset();
199 }
200 }
201
202 @Override
203 public int delete(String statement) {
204 return update(statement, null);
205 }
206
207 @Override
208 public int delete(String statement, Object parameter) {
209 return update(statement, parameter);
210 }
211
212 @Override
213 public void commit() {
214 commit(false);
215 }
216
217 @Override
218 public void commit(boolean force) {
219 try {
220 executor.commit(isCommitOrRollbackRequired(force));
221 dirty = false;
222 } catch (Exception e) {
223 throw ExceptionFactory.wrapException("Error committing transaction. Cause: " + e, e);
224 } finally {
225 ErrorContext.instance().reset();
226 }
227 }
228
229 @Override
230 public void rollback() {
231 rollback(false);
232 }
233
234 @Override
235 public void rollback(boolean force) {
236 try {
237 executor.rollback(isCommitOrRollbackRequired(force));
238 dirty = false;
239 } catch (Exception e) {
240 throw ExceptionFactory.wrapException("Error rolling back transaction. Cause: " + e, e);
241 } finally {
242 ErrorContext.instance().reset();
243 }
244 }
245
246 @Override
247 public List<BatchResult> flushStatements() {
248 try {
249 return executor.flushStatements();
250 } catch (Exception e) {
251 throw ExceptionFactory.wrapException("Error flushing statements. Cause: " + e, e);
252 } finally {
253 ErrorContext.instance().reset();
254 }
255 }
256
257 @Override
258 public void close() {
259 try {
260 executor.close(isCommitOrRollbackRequired(false));
261 closeCursors();
262 dirty = false;
263 } finally {
264 ErrorContext.instance().reset();
265 }
266 }
267
268 private void closeCursors() {
269 if (cursorList != null && !cursorList.isEmpty()) {
270 for (Cursor<?> cursor : cursorList) {
271 try {
272 cursor.close();
273 } catch (IOException e) {
274 throw ExceptionFactory.wrapException("Error closing cursor. Cause: " + e, e);
275 }
276 }
277 cursorList.clear();
278 }
279 }
280
281 @Override
282 public Configuration getConfiguration() {
283 return configuration;
284 }
285
286 @Override
287 public <T> T getMapper(Class<T> type) {
288 return configuration.getMapper(type, this);
289 }
290
291 @Override
292 public Connection getConnection() {
293 try {
294 return executor.getTransaction().getConnection();
295 } catch (SQLException e) {
296 throw ExceptionFactory.wrapException("Error getting a new connection. Cause: " + e, e);
297 }
298 }
299
300 @Override
301 public void clearCache() {
302 executor.clearLocalCache();
303 }
304
305 private <T> void registerCursor(Cursor<T> cursor) {
306 if (cursorList == null) {
307 cursorList = new ArrayList<>();
308 }
309 cursorList.add(cursor);
310 }
311
312 private boolean isCommitOrRollbackRequired(boolean force) {
313 return (!autoCommit && dirty) || force;
314 }
315
316 private Object wrapCollection(final Object object) {
317 return ParamNameResolver.wrapToMapIfCollection(object, null);
318 }
319
320
321
322
323 @Deprecated
324 public static class StrictMap<V> extends HashMap<String, V> {
325
326 private static final long serialVersionUID = -5741767162221585340L;
327
328 @Override
329 public V get(Object key) {
330 if (!super.containsKey(key)) {
331 throw new BindingException("Parameter '" + key + "' not found. Available parameters are " + this.keySet());
332 }
333 return super.get(key);
334 }
335
336 }
337
338 }