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