MybatisSqlSessionTemplate.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. /*
  2. * Copyright 2010-2016 the original author or authors.
  3. * <p>
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. * <p>
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. * <p>
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.baomidou.mybatisplus.extension;
  17. import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
  18. import org.apache.ibatis.cursor.Cursor;
  19. import org.apache.ibatis.executor.BatchResult;
  20. import org.apache.ibatis.session.*;
  21. import org.mybatis.spring.MyBatisExceptionTranslator;
  22. import org.springframework.beans.factory.DisposableBean;
  23. import org.springframework.dao.support.PersistenceExceptionTranslator;
  24. import org.springframework.util.Assert;
  25. import java.lang.reflect.InvocationHandler;
  26. import java.lang.reflect.Method;
  27. import java.sql.Connection;
  28. import java.util.List;
  29. import java.util.Map;
  30. import static java.lang.reflect.Proxy.newProxyInstance;
  31. /**
  32. * Copy SqlSessionTemplate
  33. *
  34. * @see org.mybatis.spring.SqlSessionTemplate
  35. */
  36. public class MybatisSqlSessionTemplate implements SqlSession, DisposableBean {
  37. private final SqlSessionFactory sqlSessionFactory;
  38. private final ExecutorType executorType;
  39. private final SqlSession sqlSessionProxy;
  40. private final PersistenceExceptionTranslator exceptionTranslator;
  41. /**
  42. * Constructs a Spring managed SqlSession with the {@code SqlSessionFactory}
  43. * provided as an argument.
  44. *
  45. * @param sqlSessionFactory
  46. */
  47. public MybatisSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
  48. this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
  49. }
  50. /**
  51. * Constructs a Spring managed SqlSession with the {@code SqlSessionFactory}
  52. * provided as an argument and the given {@code ExecutorType}
  53. * {@code ExecutorType} cannot be changed once the
  54. * {@code SqlSessionTemplate} is constructed.
  55. *
  56. * @param sqlSessionFactory
  57. * @param executorType
  58. */
  59. public MybatisSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
  60. this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration()
  61. .getEnvironment().getDataSource(), true));
  62. }
  63. /**
  64. * Constructs a Spring managed {@code SqlSession} with the given
  65. * {@code SqlSessionFactory} and {@code ExecutorType}. A custom
  66. * {@code SQLExceptionTranslator} can be provided as an argument so any
  67. * {@code PersistenceException} thrown by MyBatis can be custom translated
  68. * to a {@code RuntimeException} The {@code SQLExceptionTranslator} can also
  69. * be null and thus no exception translation will be done and MyBatis
  70. * exceptions will be thrown
  71. *
  72. * @param sqlSessionFactory
  73. * @param executorType
  74. * @param exceptionTranslator
  75. */
  76. public MybatisSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
  77. PersistenceExceptionTranslator exceptionTranslator) {
  78. Assert.notNull(sqlSessionFactory, "SFunction 'sqlSessionFactory' is required");
  79. Assert.notNull(executorType, "SFunction 'executorType' is required");
  80. this.sqlSessionFactory = sqlSessionFactory;
  81. this.executorType = executorType;
  82. this.exceptionTranslator = exceptionTranslator;
  83. this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
  84. new Class[]{SqlSession.class}, new SqlSessionInterceptor());
  85. }
  86. public SqlSessionFactory getSqlSessionFactory() {
  87. return this.sqlSessionFactory;
  88. }
  89. public ExecutorType getExecutorType() {
  90. return this.executorType;
  91. }
  92. public PersistenceExceptionTranslator getPersistenceExceptionTranslator() {
  93. return this.exceptionTranslator;
  94. }
  95. /**
  96. * {@inheritDoc}
  97. */
  98. @Override
  99. public <T> T selectOne(String statement) {
  100. return this.sqlSessionProxy.<T>selectOne(statement);
  101. }
  102. /**
  103. * {@inheritDoc}
  104. */
  105. @Override
  106. public <T> T selectOne(String statement, Object parameter) {
  107. return this.sqlSessionProxy.<T>selectOne(statement, parameter);
  108. }
  109. /**
  110. * {@inheritDoc}
  111. */
  112. @Override
  113. public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
  114. return this.sqlSessionProxy.<K, V>selectMap(statement, mapKey);
  115. }
  116. /**
  117. * {@inheritDoc}
  118. */
  119. @Override
  120. public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
  121. return this.sqlSessionProxy.<K, V>selectMap(statement, parameter, mapKey);
  122. }
  123. /**
  124. * {@inheritDoc}
  125. */
  126. @Override
  127. public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
  128. return this.sqlSessionProxy.<K, V>selectMap(statement, parameter, mapKey, rowBounds);
  129. }
  130. /**
  131. * {@inheritDoc}
  132. */
  133. @Override
  134. public <T> Cursor<T> selectCursor(String statement) {
  135. return this.sqlSessionProxy.selectCursor(statement);
  136. }
  137. /**
  138. * {@inheritDoc}
  139. */
  140. @Override
  141. public <T> Cursor<T> selectCursor(String statement, Object parameter) {
  142. return this.sqlSessionProxy.selectCursor(statement, parameter);
  143. }
  144. /**
  145. * {@inheritDoc}
  146. */
  147. @Override
  148. public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
  149. return this.sqlSessionProxy.selectCursor(statement, parameter, rowBounds);
  150. }
  151. /**
  152. * {@inheritDoc}
  153. */
  154. @Override
  155. public <E> List<E> selectList(String statement) {
  156. return this.sqlSessionProxy.<E>selectList(statement);
  157. }
  158. /**
  159. * {@inheritDoc}
  160. */
  161. @Override
  162. public <E> List<E> selectList(String statement, Object parameter) {
  163. return this.sqlSessionProxy.<E>selectList(statement, parameter);
  164. }
  165. /**
  166. * {@inheritDoc}
  167. */
  168. @Override
  169. public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
  170. return this.sqlSessionProxy.<E>selectList(statement, parameter, rowBounds);
  171. }
  172. /**
  173. * {@inheritDoc}
  174. */
  175. @Override
  176. public void select(String statement, ResultHandler handler) {
  177. this.sqlSessionProxy.select(statement, handler);
  178. }
  179. /**
  180. * {@inheritDoc}
  181. */
  182. @Override
  183. public void select(String statement, Object parameter, ResultHandler handler) {
  184. this.sqlSessionProxy.select(statement, parameter, handler);
  185. }
  186. /**
  187. * {@inheritDoc}
  188. */
  189. @Override
  190. public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
  191. this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
  192. }
  193. /**
  194. * {@inheritDoc}
  195. */
  196. @Override
  197. public int insert(String statement) {
  198. return this.sqlSessionProxy.insert(statement);
  199. }
  200. /**
  201. * {@inheritDoc}
  202. */
  203. @Override
  204. public int insert(String statement, Object parameter) {
  205. return this.sqlSessionProxy.insert(statement, parameter);
  206. }
  207. /**
  208. * {@inheritDoc}
  209. */
  210. @Override
  211. public int update(String statement) {
  212. return this.sqlSessionProxy.update(statement);
  213. }
  214. /**
  215. * {@inheritDoc}
  216. */
  217. @Override
  218. public int update(String statement, Object parameter) {
  219. return this.sqlSessionProxy.update(statement, parameter);
  220. }
  221. /**
  222. * {@inheritDoc}
  223. */
  224. @Override
  225. public int delete(String statement) {
  226. return this.sqlSessionProxy.delete(statement);
  227. }
  228. /**
  229. * {@inheritDoc}
  230. */
  231. @Override
  232. public int delete(String statement, Object parameter) {
  233. return this.sqlSessionProxy.delete(statement, parameter);
  234. }
  235. /**
  236. * {@inheritDoc}
  237. */
  238. @Override
  239. public <T> T getMapper(Class<T> type) {
  240. return getConfiguration().getMapper(type, this);
  241. }
  242. /**
  243. * {@inheritDoc}
  244. */
  245. @Override
  246. public void commit() {
  247. throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
  248. }
  249. /**
  250. * {@inheritDoc}
  251. */
  252. @Override
  253. public void commit(boolean force) {
  254. throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
  255. }
  256. /**
  257. * {@inheritDoc}
  258. */
  259. @Override
  260. public void rollback() {
  261. throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
  262. }
  263. /**
  264. * {@inheritDoc}
  265. */
  266. @Override
  267. public void rollback(boolean force) {
  268. throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
  269. }
  270. /**
  271. * {@inheritDoc}
  272. */
  273. @Override
  274. public void close() {
  275. throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession");
  276. }
  277. /**
  278. * {@inheritDoc}
  279. */
  280. @Override
  281. public void clearCache() {
  282. this.sqlSessionProxy.clearCache();
  283. }
  284. /**
  285. * {@inheritDoc}
  286. */
  287. @Override
  288. public Configuration getConfiguration() {
  289. return this.sqlSessionFactory.getConfiguration();
  290. }
  291. /**
  292. * {@inheritDoc}
  293. */
  294. @Override
  295. public Connection getConnection() {
  296. return this.sqlSessionProxy.getConnection();
  297. }
  298. /**
  299. * {@inheritDoc}
  300. *
  301. * @since 1.0.2
  302. */
  303. @Override
  304. public List<BatchResult> flushStatements() {
  305. return this.sqlSessionProxy.flushStatements();
  306. }
  307. /**
  308. * Allow gently dispose bean:
  309. * <p>
  310. * <p>
  311. * <pre>
  312. * {@code
  313. *
  314. * <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
  315. * <constructor-arg index="0" ref="sqlSessionFactory" />
  316. * </bean>
  317. * }
  318. * </pre>
  319. * <p>
  320. * The implementation of {@link DisposableBean} forces spring context to use
  321. * {@link DisposableBean#destroy()} method instead of
  322. * {@link MybatisSqlSessionTemplate#close()} to shutdown gently.
  323. *
  324. * @see MybatisSqlSessionTemplate#close()
  325. * @see org.springframework.beans.factory.support.DisposableBeanAdapter#inferDestroyMethodIfNecessary
  326. * @see org.springframework.beans.factory.support.DisposableBeanAdapter#CLOSE_METHOD_NAME
  327. */
  328. @Override
  329. public void destroy() throws Exception {
  330. // This method forces spring disposer to avoid call of
  331. // SqlSessionTemplate.close() which gives UnsupportedOperationException
  332. }
  333. /**
  334. * Proxy needed to route MyBatis method calls to the proper SqlSession got
  335. * from Spring's Transaction Manager It also unwraps exceptions thrown by
  336. * {@code Method#invoke(Object, Object...)} to pass a
  337. * {@code PersistenceException} to the
  338. * {@code PersistenceExceptionTranslator}.
  339. */
  340. private class SqlSessionInterceptor implements InvocationHandler {
  341. @Override
  342. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  343. SqlSession sqlSession = MybatisSqlSessionTemplate.this.sqlSessionFactory
  344. .openSession(MybatisSqlSessionTemplate.this.executorType);
  345. try {
  346. Object result = method.invoke(sqlSession, args);
  347. sqlSession.commit(true);
  348. return result;
  349. } catch (Throwable t) {
  350. throw ExceptionUtils.mpe(t);
  351. } finally {
  352. if (sqlSession != null) {
  353. sqlSession.close();
  354. }
  355. }
  356. }
  357. }
  358. }