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