/* * Copyright (c) 2011-2025, baomidou (jobob@qq.com). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.baomidou.mybatisplus.extension.toolkit; import com.baomidou.mybatisplus.core.assist.ISqlRunner; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils; import org.apache.ibatis.logging.Log; import org.apache.ibatis.logging.LogFactory; import org.apache.ibatis.parsing.GenericTokenParser; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.type.SimpleTypeRegistry; import org.mybatis.spring.SqlSessionUtils; import org.springframework.transaction.annotation.Transactional; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; /** * SqlRunner 执行 SQL *

* 自3.5.12开始,(当传入的参数是单参数时,支持使用Map,Array,List,JavaBean) *

  • 当参数为 Map 时可通过{key}进行属性访问 *
  • 当参数为 JavaBean 时可通过{property}进行属性访问 *
  • 当参数为 List 时直接访问索引 {0}
  • *

    * * @author Caratacus, nieqiurong * @since 2016-12-11 */ public class SqlRunner implements ISqlRunner { private static final Log LOG = LogFactory.getLog(SqlRunner.class); // 单例Query public static final SqlRunner DEFAULT = new SqlRunner(); /** * 实体类 (当未指定时,将使用{@link SqlHelper#FACTORY}进行会话操作) */ private Class clazz; public SqlRunner() { } public SqlRunner(Class clazz) { this.clazz = clazz; } /** * 获取默认的SqlQuery(适用于单库) * * @return this */ public static SqlRunner db() { return DEFAULT; } /** * 根据当前class对象获取SqlQuery(适用于多库) * * @param clazz 实体类 * @return this */ public static SqlRunner db(Class clazz) { return new SqlRunner(clazz); } /** * 执行插入语句 * * @param sql 指定参数的格式: {0}, {1} 或者 {property1}, {property2} * @param args 参数 * @return 插入结果 */ @Override @Transactional public boolean insert(String sql, Object... args) { SqlSession sqlSession = sqlSession(); try { return SqlHelper.retBool(sqlSession.insert(INSERT, sqlMap(sql, args))); } finally { closeSqlSession(sqlSession); } } /** * 执行删除语句 * * @param sql 指定参数的格式: {0}, {1} 或者 {property1}, {property2} * @param args 参数 * @return 删除结果 */ @Override @Transactional public boolean delete(String sql, Object... args) { SqlSession sqlSession = sqlSession(); try { return SqlHelper.retBool(sqlSession.delete(DELETE, sqlMap(sql, args))); } finally { closeSqlSession(sqlSession); } } /** * 获取sqlMap参数 *

    * 自3.5.12开始,(当传入的参数是单参数时,支持使用Map,Array,List,JavaBean) *

  • 当参数为 Map 时可通过{key}进行属性访问 *
  • 当参数为 JavaBean 时可通过{property}进行属性访问 *
  • 当参数为 List 时直接访问索引 {0}
  • *

    * * @param sql 指定参数的格式: {0}, {1} 或者 {property1}, {property2} * @param args 参数 * @return 参数集合 */ private Map sqlMap(String sql, Object... args) { Map sqlMap = getParams(args); sqlMap.put(SQL, parse(sql)); return sqlMap; } /** * 获取执行语句 * * @param sql 原始sql * @return 执行语句 * @since 3.5.12 */ private String parse(String sql) { return new GenericTokenParser("{", "}", content -> "#{" + content + "}").parse(sql); } /** * 获取参数列表 * * @param args 参数(单参数时,支持使用Map,List,JavaBean访问) * @return 参数map * @since 3.5.12 */ private Map getParams(Object... args) { if (args != null && args.length > 0) { if (args.length == 1) { // 暂定支持 Map,Collection,JavaBean Object arg = args[0]; if (arg instanceof Map) { //noinspection unchecked return new HashMap((Map) arg); } if (arg instanceof Collection) { Collection collection = (Collection) arg; Map params = new HashMap<>(CollectionUtils.newHashMapWithExpectedSize(collection.size())); Iterator iterator = collection.iterator(); int index = 0; while (iterator.hasNext()) { params.put(String.valueOf(index), iterator.next()); index++; } return params; } Class cls = arg.getClass(); if (!(cls.isPrimitive() || SimpleTypeRegistry.isSimpleType(cls) || cls.isArray() || cls.isEnum()) ) { MetaObject metaObject = SystemMetaObject.forObject(arg); String[] getterNames = metaObject.getGetterNames(); Map params = new HashMap<>(CollectionUtils.newHashMapWithExpectedSize(getterNames.length)); for (String getterName : getterNames) { params.put(getterName, metaObject.getValue(getterName)); } return params; } } Map params = CollectionUtils.newHashMapWithExpectedSize(args.length); for (int i = 0; i < args.length; i++) { params.put(String.valueOf(i), args[i]); } return params; } return new HashMap<>(); } /** * 获取sqlMap参数 * * @param sql 指定参数的格式: {0}, {1} 或者 {property1}, {property2} * @param page 分页模型 * @param args 参数 * @return 参数集合 */ private Map sqlMap(String sql, IPage page, Object... args) { Map sqlMap = getParams(args); sqlMap.put(PAGE, page); sqlMap.put(SQL, parse(sql)); return sqlMap; } /** * 执行更新语句 * * @param sql 指定参数的格式: {0}, {1} 或者 {property1}, {property2} * @param args 参数 * @return 更新结果 */ @Override @Transactional public boolean update(String sql, Object... args) { SqlSession sqlSession = sqlSession(); try { return SqlHelper.retBool(sqlSession.update(UPDATE, sqlMap(sql, args))); } finally { closeSqlSession(sqlSession); } } /** * 根据sql查询Map结果集 *

    SqlRunner.db().selectList("select * from tbl_user where name={0}", "Caratacus")

    * * @param sql sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2} * @param args 参数列表 * @return 结果集 */ @Override public List> selectList(String sql, Object... args) { SqlSession sqlSession = sqlSession(); try { return sqlSession.selectList(SELECT_LIST, sqlMap(sql, args)); } finally { closeSqlSession(sqlSession); } } /** * 根据sql查询一个字段值的结果集 *

    注意:该方法只会返回一个字段的值, 如果需要多字段,请参考{@link #selectList(String, Object...)}

    * * @param sql sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2} * @param args 参数 * @return 结果集 */ @Override public List selectObjs(String sql, Object... args) { SqlSession sqlSession = sqlSession(); try { return sqlSession.selectList(SELECT_OBJS, sqlMap(sql, args)); } finally { closeSqlSession(sqlSession); } } /** * 根据sql查询一个字段值的一条结果 *

    注意:该方法只会返回一个字段的值, 如果需要多字段,请参考{@link #selectOne(String, Object...)}

    * * @param sql sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2} * @param args 参数 * @return 结果 */ @Override public Object selectObj(String sql, Object... args) { return SqlHelper.getObject(LOG, selectObjs(sql, args)); } /** * 查询总数 * * @param sql sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2} * @param args 参数 * @return 总记录数 */ @Override public long selectCount(String sql, Object... args) { SqlSession sqlSession = sqlSession(); try { return SqlHelper.retCount(sqlSession.selectOne(COUNT, sqlMap(sql, args))); } finally { closeSqlSession(sqlSession); } } /** * 获取单条记录 * * @param sql sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2} * @param args 参数 * @return 单行结果集 (当执行语句返回多条记录时,只会选取第一条记录) */ @Override public Map selectOne(String sql, Object... args) { return SqlHelper.getObject(LOG, selectList(sql, args)); } /** * 分页查询 * * @param page 分页对象 * @param sql sql语句,可添加参数,指定参数的格式: {0}, {1} 或者 {property1}, {property2} * @param args 参数 * @param E * @return 分页数据 */ @Override public >> E selectPage(E page, String sql, Object... args) { if (null == page) { return null; } SqlSession sqlSession = sqlSession(); try { page.setRecords(sqlSession.selectList(SELECT_LIST, sqlMap(sql, page, args))); } finally { closeSqlSession(sqlSession); } return page; } /** * 获取Session 默认自动提交 */ private SqlSession sqlSession() { return SqlSessionUtils.getSqlSession(getSqlSessionFactory()); } /** * 释放sqlSession * * @param sqlSession session */ private void closeSqlSession(SqlSession sqlSession) { SqlSessionUtils.closeSqlSession(sqlSession, getSqlSessionFactory()); } /** * 获取SqlSessionFactory */ private SqlSessionFactory getSqlSessionFactory() { return Optional.ofNullable(clazz).map(GlobalConfigUtils::currentSessionFactory).orElse(SqlHelper.FACTORY); } /** * @deprecated 3.5.3.2 */ @Deprecated public void close() { } }