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 public SqlSessionFactory getSqlSessionFactory() {
136 return this.sqlSessionFactory;
137 }
138
139 public ExecutorType getExecutorType() {
140 return this.executorType;
141 }
142
143 public PersistenceExceptionTranslator getPersistenceExceptionTranslator() {
144 return this.exceptionTranslator;
145 }
146
147 @Override
148 public <T> T selectOne(String statement) {
149 return this.sqlSessionProxy.selectOne(statement);
150 }
151
152 @Override
153 public <T> T selectOne(String statement, Object parameter) {
154 return this.sqlSessionProxy.selectOne(statement, parameter);
155 }
156
157 @Override
158 public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
159 return this.sqlSessionProxy.selectMap(statement, mapKey);
160 }
161
162 @Override
163 public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
164 return this.sqlSessionProxy.selectMap(statement, parameter, mapKey);
165 }
166
167 @Override
168 public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
169 return this.sqlSessionProxy.selectMap(statement, parameter, mapKey, rowBounds);
170 }
171
172 @Override
173 public <T> Cursor<T> selectCursor(String statement) {
174 return this.sqlSessionProxy.selectCursor(statement);
175 }
176
177 @Override
178 public <T> Cursor<T> selectCursor(String statement, Object parameter) {
179 return this.sqlSessionProxy.selectCursor(statement, parameter);
180 }
181
182 @Override
183 public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
184 return this.sqlSessionProxy.selectCursor(statement, parameter, rowBounds);
185 }
186
187 @Override
188 public <E> List<E> selectList(String statement) {
189 return this.sqlSessionProxy.selectList(statement);
190 }
191
192 @Override
193 public <E> List<E> selectList(String statement, Object parameter) {
194 return this.sqlSessionProxy.selectList(statement, parameter);
195 }
196
197 @Override
198 public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
199 return this.sqlSessionProxy.selectList(statement, parameter, rowBounds);
200 }
201
202 @Override
203 public void select(String statement, ResultHandler handler) {
204 this.sqlSessionProxy.select(statement, handler);
205 }
206
207 @Override
208 public void select(String statement, Object parameter, ResultHandler handler) {
209 this.sqlSessionProxy.select(statement, parameter, handler);
210 }
211
212 @Override
213 public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
214 this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
215 }
216
217 @Override
218 public int insert(String statement) {
219 return this.sqlSessionProxy.insert(statement);
220 }
221
222 @Override
223 public int insert(String statement, Object parameter) {
224 return this.sqlSessionProxy.insert(statement, parameter);
225 }
226
227 @Override
228 public int update(String statement) {
229 return this.sqlSessionProxy.update(statement);
230 }
231
232 @Override
233 public int update(String statement, Object parameter) {
234 return this.sqlSessionProxy.update(statement, parameter);
235 }
236
237 @Override
238 public int delete(String statement) {
239 return this.sqlSessionProxy.delete(statement);
240 }
241
242 @Override
243 public int delete(String statement, Object parameter) {
244 return this.sqlSessionProxy.delete(statement, parameter);
245 }
246
247 @Override
248 public <T> T getMapper(Class<T> type) {
249 return getConfiguration().getMapper(type, this);
250 }
251
252 @Override
253 public void commit() {
254 throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
255 }
256
257 @Override
258 public void commit(boolean force) {
259 throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
260 }
261
262 @Override
263 public void rollback() {
264 throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
265 }
266
267 @Override
268 public void rollback(boolean force) {
269 throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
270 }
271
272 @Override
273 public void close() {
274 throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession");
275 }
276
277 @Override
278 public void clearCache() {
279 this.sqlSessionProxy.clearCache();
280 }
281
282 @Override
283 public Configuration getConfiguration() {
284 return this.sqlSessionFactory.getConfiguration();
285 }
286
287 @Override
288 public Connection getConnection() {
289 return this.sqlSessionProxy.getConnection();
290 }
291
292 @Override
293 public List<BatchResult> flushStatements() {
294 return this.sqlSessionProxy.flushStatements();
295 }
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316 @Override
317 public void destroy() throws Exception {
318
319
320 }
321
322
323
324
325
326
327 private class SqlSessionInterceptor implements InvocationHandler {
328 @Override
329 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
330 var sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType,
331 SqlSessionTemplate.this.exceptionTranslator);
332 try {
333 var result = method.invoke(sqlSession, args);
334 if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
335
336
337 sqlSession.commit(true);
338 }
339 return result;
340 } catch (Throwable t) {
341 var unwrapped = unwrapThrowable(t);
342 if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
343
344 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
345 sqlSession = null;
346 Throwable translated = SqlSessionTemplate.this.exceptionTranslator
347 .translateExceptionIfPossible((PersistenceException) unwrapped);
348 if (translated != null) {
349 unwrapped = translated;
350 }
351 }
352 throw unwrapped;
353 } finally {
354 if (sqlSession != null) {
355 closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
356 }
357 }
358 }
359 }
360
361 }