1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mybatis.spring;
17
18 import static java.lang.reflect.Proxy.newProxyInstance;
19
20 import static org.apache.ibatis.reflection.ExceptionUtil.unwrapThrowable;
21 import static org.mybatis.spring.SqlSessionUtils.closeSqlSession;
22 import static org.mybatis.spring.SqlSessionUtils.getSqlSession;
23 import static org.mybatis.spring.SqlSessionUtils.isSqlSessionTransactional;
24 import static org.springframework.util.Assert.notNull;
25
26 import java.lang.reflect.InvocationHandler;
27 import java.lang.reflect.Method;
28 import java.sql.Connection;
29 import java.util.List;
30 import java.util.Map;
31
32 import org.apache.ibatis.cursor.Cursor;
33 import org.apache.ibatis.exceptions.PersistenceException;
34 import org.apache.ibatis.executor.BatchResult;
35 import org.apache.ibatis.session.Configuration;
36 import org.apache.ibatis.session.ExecutorType;
37 import org.apache.ibatis.session.ResultHandler;
38 import org.apache.ibatis.session.RowBounds;
39 import org.apache.ibatis.session.SqlSession;
40 import org.apache.ibatis.session.SqlSessionFactory;
41 import org.springframework.beans.factory.DisposableBean;
42 import org.springframework.dao.support.PersistenceExceptionTranslator;
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 public class SqlSessionTemplate implements SqlSession, DisposableBean {
76
77 private final SqlSessionFactory sqlSessionFactory;
78
79 private final ExecutorType executorType;
80
81 private final SqlSession sqlSessionProxy;
82
83 private final PersistenceExceptionTranslator exceptionTranslator;
84
85
86
87
88
89
90
91 public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
92 this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
93 }
94
95
96
97
98
99
100
101
102
103
104 public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
105 this(sqlSessionFactory, executorType,
106 new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration().getEnvironment().getDataSource(), true));
107 }
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
123 PersistenceExceptionTranslator exceptionTranslator) {
124
125 notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
126 notNull(executorType, "Property 'executorType' is required");
127
128 this.sqlSessionFactory = sqlSessionFactory;
129 this.executorType = executorType;
130 this.exceptionTranslator = exceptionTranslator;
131 this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
132 new Class[] { SqlSession.class }, new SqlSessionInterceptor());
133 }
134
135
136
137
138
139
140 public SqlSessionFactory getSqlSessionFactory() {
141 return this.sqlSessionFactory;
142 }
143
144
145
146
147
148
149 public ExecutorType getExecutorType() {
150 return this.executorType;
151 }
152
153
154
155
156
157
158 public PersistenceExceptionTranslator getPersistenceExceptionTranslator() {
159 return this.exceptionTranslator;
160 }
161
162 @Override
163 public <T> T selectOne(String statement) {
164 return this.sqlSessionProxy.selectOne(statement);
165 }
166
167 @Override
168 public <T> T selectOne(String statement, Object parameter) {
169 return this.sqlSessionProxy.selectOne(statement, parameter);
170 }
171
172 @Override
173 public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
174 return this.sqlSessionProxy.selectMap(statement, mapKey);
175 }
176
177 @Override
178 public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
179 return this.sqlSessionProxy.selectMap(statement, parameter, mapKey);
180 }
181
182 @Override
183 public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
184 return this.sqlSessionProxy.selectMap(statement, parameter, mapKey, rowBounds);
185 }
186
187 @Override
188 public <T> Cursor<T> selectCursor(String statement) {
189 return this.sqlSessionProxy.selectCursor(statement);
190 }
191
192 @Override
193 public <T> Cursor<T> selectCursor(String statement, Object parameter) {
194 return this.sqlSessionProxy.selectCursor(statement, parameter);
195 }
196
197 @Override
198 public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
199 return this.sqlSessionProxy.selectCursor(statement, parameter, rowBounds);
200 }
201
202 @Override
203 public <E> List<E> selectList(String statement) {
204 return this.sqlSessionProxy.selectList(statement);
205 }
206
207 @Override
208 public <E> List<E> selectList(String statement, Object parameter) {
209 return this.sqlSessionProxy.selectList(statement, parameter);
210 }
211
212 @Override
213 public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
214 return this.sqlSessionProxy.selectList(statement, parameter, rowBounds);
215 }
216
217 @Override
218 public void select(String statement, ResultHandler handler) {
219 this.sqlSessionProxy.select(statement, handler);
220 }
221
222 @Override
223 public void select(String statement, Object parameter, ResultHandler handler) {
224 this.sqlSessionProxy.select(statement, parameter, handler);
225 }
226
227 @Override
228 public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
229 this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
230 }
231
232 @Override
233 public int insert(String statement) {
234 return this.sqlSessionProxy.insert(statement);
235 }
236
237 @Override
238 public int insert(String statement, Object parameter) {
239 return this.sqlSessionProxy.insert(statement, parameter);
240 }
241
242 @Override
243 public int update(String statement) {
244 return this.sqlSessionProxy.update(statement);
245 }
246
247 @Override
248 public int update(String statement, Object parameter) {
249 return this.sqlSessionProxy.update(statement, parameter);
250 }
251
252 @Override
253 public int delete(String statement) {
254 return this.sqlSessionProxy.delete(statement);
255 }
256
257 @Override
258 public int delete(String statement, Object parameter) {
259 return this.sqlSessionProxy.delete(statement, parameter);
260 }
261
262 @Override
263 public <T> T getMapper(Class<T> type) {
264 return getConfiguration().getMapper(type, this);
265 }
266
267 @Override
268 public void commit() {
269 throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
270 }
271
272 @Override
273 public void commit(boolean force) {
274 throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
275 }
276
277 @Override
278 public void rollback() {
279 throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
280 }
281
282 @Override
283 public void rollback(boolean force) {
284 throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
285 }
286
287 @Override
288 public void close() {
289 throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession");
290 }
291
292 @Override
293 public void clearCache() {
294 this.sqlSessionProxy.clearCache();
295 }
296
297 @Override
298 public Configuration getConfiguration() {
299 return this.sqlSessionFactory.getConfiguration();
300 }
301
302 @Override
303 public Connection getConnection() {
304 return this.sqlSessionProxy.getConnection();
305 }
306
307 @Override
308 public List<BatchResult> flushStatements() {
309 return this.sqlSessionProxy.flushStatements();
310 }
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331 @Override
332 public void destroy() throws Exception {
333
334
335 }
336
337
338
339
340
341
342 private class SqlSessionInterceptor implements InvocationHandler {
343 @Override
344 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
345 var sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType,
346 SqlSessionTemplate.this.exceptionTranslator);
347 try {
348 var result = method.invoke(sqlSession, args);
349 if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
350
351
352 sqlSession.commit(true);
353 }
354 return result;
355 } catch (Throwable t) {
356 var unwrapped = unwrapThrowable(t);
357 if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
358
359 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
360 sqlSession = null;
361 Throwable translated = SqlSessionTemplate.this.exceptionTranslator
362 .translateExceptionIfPossible((PersistenceException) unwrapped);
363 if (translated != null) {
364 unwrapped = translated;
365 }
366 }
367 throw unwrapped;
368 } finally {
369 if (sqlSession != null) {
370 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
371 }
372 }
373 }
374 }
375
376 }