您当前的位置:首页 > 电脑百科 > 程序开发 > 架构

MyBatis源码解读 | 使用SqlRunner操作数据库

时间:2022-07-05 11:01:55  来源:  作者:嗨皮汪小成

简介

SqlRunner,一个非常实用的、用于操作数据库的工具类。该类对JDBC进行了很好的封装,结合SQL工具类,能够很方便地通过JAVA代码执行SQL语句并检索SQL执行结果。

SqlRunner提供了如下同个用于操作数据库的方法:

  • selectOne(String sql, Object... args):执行SELECT查询语句,返回一条数据;
  • selectAll(String sql, Object... args):执行SELECT查询语句,返回多条数据;
  • insert(String sql, Object... args):执行INSERT语句;
  • update(String sql, Object… args):执行UPDATE语句;
  • delete(String sql, Object... args):执行DELETE语句;
  • run(String sql):运行任意一条SQL语句。

示例

SqlRunner使用示例:

try {
    // 数据库连接
    Connection connection = DriverManager.getConnection("jdbc:MySQL://127.0.0.1/MyBatis?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC", "root", "abc123");
    // 创建SqlRunner实例
    SqlRunner sqlRunner = new SqlRunner(connection);
    // 要执行的SQL语句
    String sql = "select * from t_transfer_log";
    // 执行SQL语句,获取返回结果
    List<Map<String, Object>> resultList = sqlRunner.selectAll(sql);
    // 遍历并输出返回结果内容
    for (Map<String, Object> itemMap : resultList) {
        System.out.println(new Gson().toJson(itemMap));
    }
} catch (Exception e) {
    e.printStackTrace();
}

源码

selectAll()方法源码:

public List<Map<String, Object>> selectAll(String sql, Object... args) throws SQLException {
  try (PreparedStatement ps = connection.prepareStatement(sql)) {
    // 为SQL中的参数赋值
    setParameters(ps, args);
    // 执行查询操作
    try (ResultSet rs = ps.executeQuery()) {
      // 将查询结果转换为List
      return getResults(rs);
    }
  }
}

setParameters()方法源码:

private void setParameters(PreparedStatement ps, Object... args) throws SQLException {
  for (int i = 0, n = args.length; i < n; i++) {
    if (args[i] == null) {
      throw new SQLException("SqlRunner requires an instance of Null to represent typed null values for JDBC compatibility");
    } else if (args[i] instanceof Null) {
      ((Null) args[i]).getTypeHandler().setParameter(ps, i + 1, null, ((Null) args[i]).getJdbcType());
    } else {
      // 根据参数类型获取对应的类型处理器
      TypeHandler typeHandler = typeHandlerRegistry.getTypeHandler(args[i].getClass());
      if (typeHandler == null) {
        throw new SQLException("SqlRunner could not find a TypeHandler instance for " + args[i].getClass());
      } else {
        // 调用类型处理器的setParameter()方法设置参数值
        typeHandler.setParameter(ps, i + 1, args[i], null);
      }
    }
  }
}

setParameters()方法处理逻辑:根据参数类型获取对应的类型处理器,如果没有对应的类型处理器会抛异常,获取到类型处理器后会调用类型处理器的setParameter()方法设置参数值。

getResults()方法源码:

private List<Map<String, Object>> getResults(ResultSet rs) throws SQLException {
  // 返回结果
  List<Map<String, Object>> list = new ArrayList<>();
  List<String> columns = new ArrayList<>();
  List<TypeHandler<?>> typeHandlers = new ArrayList<>();
  // 获取ResultSetMetaData对象
  ResultSetMetaData rsmd = rs.getMetaData();
  // 遍历获取列名、类型处理器
  for (int i = 0, n = rsmd.getColumnCount(); i < n; i++) {
    columns.add(rsmd.getColumnLabel(i + 1));
    try {
      Class<?> type = Resources.classForName(rsmd.getColumnClassName(i + 1));
      TypeHandler<?> typeHandler = typeHandlerRegistry.getTypeHandler(type);
      if (typeHandler == null) {
        typeHandler = typeHandlerRegistry.getTypeHandler(Object.class);
      }
      typeHandlers.add(typeHandler);
    } catch (Exception e) {
      typeHandlers.add(typeHandlerRegistry.getTypeHandler(Object.class));
    }
  }
  // 遍历ResultSet将SQL执行结果转换成List<Map<String, Object>>,列名小写
  while (rs.next()) {
    Map<String, Object> row = new HashMap<>();
    for (int i = 0, n = columns.size(); i < n; i++) {
      String name = columns.get(i);
      TypeHandler<?> handler = typeHandlers.get(i);
      row.put(name.toUpperCase(Locale.ENGLISH), handler.getResult(rs, name));
    }
    list.add(row);
  }
  return list;
}


Tags:SqlRunner   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
MyBatis源码解读 | 使用SqlRunner操作数据库
简介SqlRunner,一个非常实用的、用于操作数据库的工具类。该类对JDBC进行了很好的封装,结合SQL工具类,能够很方便地通过Java代码执行SQL语句并检索SQL执行结果。SqlRunner提供...【详细内容】
2022-07-05  Search: SqlRunner  点击:(908)  评论:(0)  加入收藏
▌简易百科推荐
对于微服务架构监控应该遵守的原则
随着软件交付方式的变革,微服务架构的兴起使得软件开发变得更加快速和灵活。在这种情况下,监控系统成为了微服务控制系统的核心组成部分。随着软件的复杂性不断增加,了解系统的...【详细内容】
2024-04-03  步步运维步步坑    Tags:架构   点击:(7)  评论:(0)  加入收藏
大模型应用的 10 种架构模式
作者 | 曹洪伟在塑造新领域的过程中,我们往往依赖于一些经过实践验证的策略、方法和模式。这种观念对于软件工程领域的专业人士来说,已经司空见惯,设计模式已成为程序员们的重...【详细内容】
2024-03-27    InfoQ  Tags:架构模式   点击:(20)  评论:(0)  加入收藏
哈啰云原生架构落地实践
一、弹性伸缩技术实践1.全网容器化后一线研发的使用问题全网容器化后一线研发会面临一系列使用问题,包括时机、容量、效率和成本问题,弹性伸缩是云原生容器化后的必然技术选择...【详细内容】
2024-03-27  哈啰技术  微信公众号  Tags:架构   点击:(13)  评论:(0)  加入收藏
DDD 与 CQRS 才是黄金组合
在日常工作中,你是否也遇到过下面几种情况: 使用一个已有接口进行业务开发,上线后出现严重的性能问题,被老板当众质疑:“你为什么不使用缓存接口,这个接口全部走数据库,这怎么能扛...【详细内容】
2024-03-27  dbaplus社群    Tags:DDD   点击:(16)  评论:(0)  加入收藏
高并发架构设计(三大利器:缓存、限流和降级)
软件系统有三个追求:高性能、高并发、高可用,俗称三高。本篇讨论高并发,从高并发是什么到高并发应对的策略、缓存、限流、降级等。引言1.高并发背景互联网行业迅速发展,用户量剧...【详细内容】
2024-03-13    阿里云开发者  Tags:高并发   点击:(12)  评论:(0)  加入收藏
如何判断架构设计的优劣?
架构设计的基本准则是非常重要的,它们指导着我们如何构建可靠、可维护、可测试的系统。下面是这些准则的转换表达方式:简单即美(KISS):KISS原则的核心思想是保持简单。在设计系统...【详细内容】
2024-02-20  二进制跳动  微信公众号  Tags:架构设计   点击:(41)  评论:(0)  加入收藏
详解基于SpringBoot的WebSocket应用开发
在现代Web应用中,实时交互和数据推送的需求日益增长。WebSocket协议作为一种全双工通信协议,允许服务端与客户端之间建立持久性的连接,实现实时、双向的数据传输,极大地提升了用...【详细内容】
2024-01-30  ijunfu  今日头条  Tags:SpringBoot   点击:(23)  评论:(0)  加入收藏
PHP+Go 开发仿简书,实战高并发高可用微服务架构
来百度APP畅享高清图片//下栽のke:chaoxingit.com/2105/PHP和Go语言结合,可以开发出高效且稳定的仿简书应用。在实现高并发和高可用微服务架构时,我们可以采用一些关键技术。首...【详细内容】
2024-01-14  547蓝色星球    Tags:架构   点击:(125)  评论:(0)  加入收藏
GraalVM与Spring Boot 3.0:加速应用性能的完美融合
在2023年,SpringBoot3.0的发布标志着Spring框架对GraalVM的全面支持,这一支持是对Spring技术栈的重要补充。GraalVM是一个高性能的多语言虚拟机,它提供了Ahead-of-Time(AOT)编...【详细内容】
2024-01-11    王建立  Tags:Spring Boot   点击:(135)  评论:(0)  加入收藏
Spring Boot虚拟线程的性能还不如Webflux?
早上看到一篇关于Spring Boot虚拟线程和Webflux性能对比的文章,觉得还不错。内容较长,抓重点给大家介绍一下这篇文章的核心内容,方便大家快速阅读。测试场景作者采用了一个尽可...【详细内容】
2024-01-10  互联网架构小马哥    Tags:Spring Boot   点击:(135)  评论:(0)  加入收藏
相关文章
    无相关信息
站内最新
站内热门
站内头条