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