SqlRunner.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /*
  2. * Copyright (c) 2011-2025, baomidou (jobob@qq.com).
  3. *
  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. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  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.toolkit;
  17. import com.baomidou.mybatisplus.core.assist.ISqlRunner;
  18. import com.baomidou.mybatisplus.core.metadata.IPage;
  19. import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
  20. import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
  21. import org.apache.ibatis.logging.Log;
  22. import org.apache.ibatis.logging.LogFactory;
  23. import org.apache.ibatis.parsing.GenericTokenParser;
  24. import org.apache.ibatis.reflection.MetaObject;
  25. import org.apache.ibatis.reflection.SystemMetaObject;
  26. import org.apache.ibatis.session.SqlSession;
  27. import org.apache.ibatis.session.SqlSessionFactory;
  28. import org.apache.ibatis.type.SimpleTypeRegistry;
  29. import org.mybatis.spring.SqlSessionUtils;
  30. import org.springframework.transaction.annotation.Transactional;
  31. import java.util.Collection;
  32. import java.util.HashMap;
  33. import java.util.Iterator;
  34. import java.util.List;
  35. import java.util.Map;
  36. import java.util.Optional;
  37. /**
  38. * SqlRunner 执行 SQL
  39. * <p>
  40. * 自3.5.12开始,(当传入的参数是单参数时,支持使用Map,Array,List,JavaBean)
  41. * <li>当参数为 Map 时可通过{key}进行属性访问
  42. * <li>当参数为 JavaBean 时可通过{property}进行属性访问
  43. * <li>当参数为 List 时直接访问索引 {0} </li>
  44. * </p>
  45. *
  46. * @author Caratacus, nieqiurong
  47. * @since 2016-12-11
  48. */
  49. public class SqlRunner implements ISqlRunner {
  50. private static final Log LOG = LogFactory.getLog(SqlRunner.class);
  51. // 单例Query
  52. public static final SqlRunner DEFAULT = new SqlRunner();
  53. /**
  54. * 实体类 (当未指定时,将使用{@link SqlHelper#FACTORY}进行会话操作)
  55. */
  56. private Class<?> clazz;
  57. public SqlRunner() {
  58. }
  59. public SqlRunner(Class<?> clazz) {
  60. this.clazz = clazz;
  61. }
  62. /**
  63. * 获取默认的SqlQuery(适用于单库)
  64. *
  65. * @return this
  66. */
  67. public static SqlRunner db() {
  68. return DEFAULT;
  69. }
  70. /**
  71. * 根据当前class对象获取SqlQuery(适用于多库)
  72. *
  73. * @param clazz 实体类
  74. * @return this
  75. */
  76. public static SqlRunner db(Class<?> clazz) {
  77. return new SqlRunner(clazz);
  78. }
  79. /**
  80. * 执行插入语句
  81. *
  82. * @param sql 指定参数的格式: {0}, {1} 或者 {property1}, {property2}
  83. * @param args 参数
  84. * @return 插入结果
  85. */
  86. @Override
  87. @Transactional
  88. public boolean insert(String sql, Object... args) {
  89. SqlSession sqlSession = sqlSession();
  90. try {
  91. return SqlHelper.retBool(sqlSession.insert(INSERT, sqlMap(sql, args)));
  92. } finally {
  93. closeSqlSession(sqlSession);
  94. }
  95. }
  96. /**
  97. * 执行删除语句
  98. *
  99. * @param sql 指定参数的格式: {0}, {1} 或者 {property1}, {property2}
  100. * @param args 参数
  101. * @return 删除结果
  102. */
  103. @Override
  104. @Transactional
  105. public boolean delete(String sql, Object... args) {
  106. SqlSession sqlSession = sqlSession();
  107. try {
  108. return SqlHelper.retBool(sqlSession.delete(DELETE, sqlMap(sql, args)));
  109. } finally {
  110. closeSqlSession(sqlSession);
  111. }
  112. }
  113. /**
  114. * 获取sqlMap参数
  115. * <p>
  116. * 自3.5.12开始,(当传入的参数是单参数时,支持使用Map,Array,List,JavaBean)
  117. * <li>当参数为 Map 时可通过{key}进行属性访问
  118. * <li>当参数为 JavaBean 时可通过{property}进行属性访问
  119. * <li>当参数为 List 时直接访问索引 {0} </li>
  120. * </p>
  121. *
  122. * @param sql 指定参数的格式: {0}, {1} 或者 {property1}, {property2}
  123. * @param args 参数
  124. * @return 参数集合
  125. */
  126. private Map<String, Object> sqlMap(String sql, Object... args) {
  127. Map<String, Object> sqlMap = getParams(args);
  128. sqlMap.put(SQL, parse(sql));
  129. return sqlMap;
  130. }
  131. /**
  132. * 获取执行语句
  133. *
  134. * @param sql 原始sql
  135. * @return 执行语句
  136. * @since 3.5.12
  137. */
  138. private String parse(String sql) {
  139. return new GenericTokenParser("{", "}", content -> "#{" + content + "}").parse(sql);
  140. }
  141. /**
  142. * 获取参数列表
  143. *
  144. * @param args 参数(单参数时,支持使用Map,List,JavaBean访问)
  145. * @return 参数map
  146. * @since 3.5.12
  147. */
  148. private Map<String, Object> getParams(Object... args) {
  149. if (args != null && args.length > 0) {
  150. if (args.length == 1) {
  151. // 暂定支持 Map,Collection,JavaBean
  152. Object arg = args[0];
  153. if (arg instanceof Map) {
  154. //noinspection unchecked
  155. return new HashMap<String, Object>((Map) arg);
  156. }
  157. if (arg instanceof Collection) {
  158. Collection<?> collection = (Collection<?>) arg;
  159. Map<String, Object> params = new HashMap<>(CollectionUtils.newHashMapWithExpectedSize(collection.size()));
  160. Iterator<?> iterator = collection.iterator();
  161. int index = 0;
  162. while (iterator.hasNext()) {
  163. params.put(String.valueOf(index), iterator.next());
  164. index++;
  165. }
  166. return params;
  167. }
  168. Class<?> cls = arg.getClass();
  169. if (!(cls.isPrimitive()
  170. || SimpleTypeRegistry.isSimpleType(cls)
  171. || cls.isArray() || cls.isEnum())
  172. ) {
  173. MetaObject metaObject = SystemMetaObject.forObject(arg);
  174. String[] getterNames = metaObject.getGetterNames();
  175. Map<String, Object> params = new HashMap<>(CollectionUtils.newHashMapWithExpectedSize(getterNames.length));
  176. for (String getterName : getterNames) {
  177. params.put(getterName, metaObject.getValue(getterName));
  178. }
  179. return params;
  180. }
  181. }
  182. Map<String, Object> params = CollectionUtils.newHashMapWithExpectedSize(args.length);
  183. for (int i = 0; i < args.length; i++) {
  184. params.put(String.valueOf(i), args[i]);
  185. }
  186. return params;
  187. }
  188. return new HashMap<>();
  189. }
  190. /**
  191. * 获取sqlMap参数
  192. *
  193. * @param sql 指定参数的格式: {0}, {1} 或者 {property1}, {property2}
  194. * @param page 分页模型
  195. * @param args 参数
  196. * @return 参数集合
  197. */
  198. private Map<String, Object> sqlMap(String sql, IPage<?> page, Object... args) {
  199. Map<String, Object> sqlMap = getParams(args);
  200. sqlMap.put(PAGE, page);
  201. sqlMap.put(SQL, parse(sql));
  202. return sqlMap;
  203. }
  204. /**
  205. * 执行更新语句
  206. *
  207. * @param sql 指定参数的格式: {0}, {1} 或者 {property1}, {property2}
  208. * @param args 参数
  209. * @return 更新结果
  210. */
  211. @Override
  212. @Transactional
  213. public boolean update(String sql, Object... args) {
  214. SqlSession sqlSession = sqlSession();
  215. try {
  216. return SqlHelper.retBool(sqlSession.update(UPDATE, sqlMap(sql, args)));
  217. } finally {
  218. closeSqlSession(sqlSession);
  219. }
  220. }
  221. /**
  222. * 根据sql查询Map结果集
  223. * <p>SqlRunner.db().selectList("select * from tbl_user where name={0}", "Caratacus")</p>
  224. *
  225. * @param sql sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2}
  226. * @param args 参数列表
  227. * @return 结果集
  228. */
  229. @Override
  230. public List<Map<String, Object>> selectList(String sql, Object... args) {
  231. SqlSession sqlSession = sqlSession();
  232. try {
  233. return sqlSession.selectList(SELECT_LIST, sqlMap(sql, args));
  234. } finally {
  235. closeSqlSession(sqlSession);
  236. }
  237. }
  238. /**
  239. * 根据sql查询一个字段值的结果集
  240. * <p>注意:该方法只会返回一个字段的值, 如果需要多字段,请参考{@link #selectList(String, Object...)}</p>
  241. *
  242. * @param sql sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2}
  243. * @param args 参数
  244. * @return 结果集
  245. */
  246. @Override
  247. public List<Object> selectObjs(String sql, Object... args) {
  248. SqlSession sqlSession = sqlSession();
  249. try {
  250. return sqlSession.selectList(SELECT_OBJS, sqlMap(sql, args));
  251. } finally {
  252. closeSqlSession(sqlSession);
  253. }
  254. }
  255. /**
  256. * 根据sql查询一个字段值的一条结果
  257. * <p>注意:该方法只会返回一个字段的值, 如果需要多字段,请参考{@link #selectOne(String, Object...)}</p>
  258. *
  259. * @param sql sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2}
  260. * @param args 参数
  261. * @return 结果
  262. */
  263. @Override
  264. public Object selectObj(String sql, Object... args) {
  265. return SqlHelper.getObject(LOG, selectObjs(sql, args));
  266. }
  267. /**
  268. * 查询总数
  269. *
  270. * @param sql sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2}
  271. * @param args 参数
  272. * @return 总记录数
  273. */
  274. @Override
  275. public long selectCount(String sql, Object... args) {
  276. SqlSession sqlSession = sqlSession();
  277. try {
  278. return SqlHelper.retCount(sqlSession.<Long>selectOne(COUNT, sqlMap(sql, args)));
  279. } finally {
  280. closeSqlSession(sqlSession);
  281. }
  282. }
  283. /**
  284. * 获取单条记录
  285. *
  286. * @param sql sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2}
  287. * @param args 参数
  288. * @return 单行结果集 (当执行语句返回多条记录时,只会选取第一条记录)
  289. */
  290. @Override
  291. public Map<String, Object> selectOne(String sql, Object... args) {
  292. return SqlHelper.getObject(LOG, selectList(sql, args));
  293. }
  294. /**
  295. * 分页查询
  296. *
  297. * @param page 分页对象
  298. * @param sql sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2}
  299. * @param args 参数
  300. * @param <E> E
  301. * @return 分页数据
  302. */
  303. @Override
  304. public <E extends IPage<Map<String, Object>>> E selectPage(E page, String sql, Object... args) {
  305. if (null == page) {
  306. return null;
  307. }
  308. SqlSession sqlSession = sqlSession();
  309. try {
  310. page.setRecords(sqlSession.selectList(SELECT_LIST, sqlMap(sql, page, args)));
  311. } finally {
  312. closeSqlSession(sqlSession);
  313. }
  314. return page;
  315. }
  316. /**
  317. * 获取Session 默认自动提交
  318. */
  319. private SqlSession sqlSession() {
  320. return SqlSessionUtils.getSqlSession(getSqlSessionFactory());
  321. }
  322. /**
  323. * 释放sqlSession
  324. *
  325. * @param sqlSession session
  326. */
  327. private void closeSqlSession(SqlSession sqlSession) {
  328. SqlSessionUtils.closeSqlSession(sqlSession, getSqlSessionFactory());
  329. }
  330. /**
  331. * 获取SqlSessionFactory
  332. */
  333. private SqlSessionFactory getSqlSessionFactory() {
  334. return Optional.ofNullable(clazz).map(GlobalConfigUtils::currentSessionFactory).orElse(SqlHelper.FACTORY);
  335. }
  336. /**
  337. * @deprecated 3.5.3.2
  338. */
  339. @Deprecated
  340. public void close() {
  341. }
  342. }