0%

MyBatis StatementHandler 深度解析:数据库交互的核心执行者

StatementHandler 是 MyBatis 中直接与数据库交互的核心接口,负责管理 JDBC 的 Statement 对象(Statement/PreparedStatement/CallableStatement),协调 ParameterHandler(参数设置)和 ResultSetHandler(结果映射),完成 “SQL 预编译→参数绑定→SQL 执行→结果处理” 的全流程。从 “接口定位→架构设计→核心实现→调用链路” 四个维度,彻底拆解 StatementHandler 的工作机制,并揭示其背后的设计模式。

StatementHandler 核心定位与接口规范

核心职责

StatementHandler 是 MyBatis 与数据库交互的 “最后一公里”,核心职责可概括为 5 点:

  1. 创建 Statement 对象:根据 SQL 类型(无参数 / 预编译 / 存储过程)创建对应的 JDBC Statement
  2. SQL 预编译:对预编译 SQL(PreparedStatement)进行编译,提升执行效率;
  3. 参数绑定:委托 ParameterHandler 为 SQL 占位符(?)设置参数;
  4. SQL 执行:执行 select/insert/update/delete 及批量操作;
  5. 结果转发:将执行结果(ResultSet)委托 ResultSetHandler 映射为 Java 对象。

接口定义:核心方法规范

StatementHandler 接口定义了数据库交互的标准方法,所有实现类需遵循该规范:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public interface StatementHandler {
// 1. 从数据库连接中创建 Statement 对象(预编译 SQL 在此步骤)
Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException;

// 2. 为 Statement 绑定参数(仅 PreparedStatement/CallableStatement 需实现)
void parameterize(Statement statement) throws SQLException;

// 3. 批量执行 SQL(添加 SQL 到批量队列)
void batch(Statement statement) throws SQLException;

// 4. 执行 update/insert/delete,返回受影响行数
int update(Statement statement) throws SQLException;

// 5. 执行 select,返回结果列表(委托 ResultSetHandler 处理)
<E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException;

// 6. 执行 select,返回游标(流式读取大数据量)
<E> Cursor<E> queryCursor(Statement statement) throws SQLException;

// 7. 获取当前 SQL 对应的 BoundSql(封装 SQL 语句、参数映射等)
BoundSql getBoundSql();

// 8. 获取当前 StatementHandler 关联的 ParameterHandler
ParameterHandler getParameterHandler();
}

架构设计:接口 + 抽象基类 + 具体实现(模板方法 + 策略模式)

MyBatis 对 StatementHandler 的实现采用 “接口定义规范 + 抽象基类封装通用逻辑 + 具体类实现差异化功能” 的架构,并通过 模板方法模式(抽象基类)和 策略模式(路由类)降低耦合,提升扩展性。

架构层级图

阅读全文 »

MyBatis 执行器(Executor)深度解析:从架构到实战

Executor 是 MyBatis 的核心执行引擎,负责数据库操作的调度、缓存管理与事务控制,是 SqlSession 方法的实际执行者。MyBatis 通过 ExecutorType 提供三种基础执行器(SimpleExecutor/ReuseExecutor/BatchExecutor),并通过 CachingExecutor 实现二级缓存,形成 “基础执行 + 缓存增强” 的装饰器架构。从 “架构设计→核心实现→缓存机制→实战选型” 四个维度,彻底拆解 Executor 的工作原理。

Executor 核心定位与架构

核心职责

Executor 是 MyBatis 与数据库交互的 “总指挥”,核心职责包括:

  • 调度 StatementHandler/ParameterHandler/ResultSetHandler 完成 SQL 执行;
  • 管理一级缓存(会话级)和二级缓存(应用级);
  • 控制事务提交 / 回滚,处理批量 SQL 执行;
  • 生成缓存键(CacheKey),实现缓存命中逻辑。

架构设计:接口 + 抽象基类 + 具体实现

MyBatis 采用 “接口定义规范 + 抽象类封装通用逻辑 + 具体类实现差异化功能” 的设计,同时通过装饰器模式CachingExecutor)增强缓存能力:

graph TD
    A[Executor 接口] --> B[BaseExecutor 抽象类]
    B --> C[SimpleExecutor 简易执行器]
    B --> D[ReuseExecutor 复用执行器]
    B --> E[BatchExecutor 批量执行器]
    A --> F[CachingExecutor 缓存执行器 装饰器]
    F --> B[包装 BaseExecutor 子类]
  • 接口(Executor):定义数据库操作的核心方法(update/query/commit/rollback 等);
  • 抽象基类(BaseExecutor):实现通用逻辑(一级缓存、事务管理、延迟加载),暴露 doUpdate/doQuery 等抽象方法由子类实现;
  • 具体执行器:实现差异化 SQL 执行逻辑(如 Statement 复用、批量处理);
  • 装饰器(CachingExecutor):包装基础执行器,添加二级缓存功能,不改变原有执行逻辑。

ExecutorType 枚举:执行器类型

MyBatis 通过 ExecutorType 枚举指定执行器类型,决定 SQL 执行策略:

ExecutorType 对应执行器 核心特点 适用场景
SIMPLE SimpleExecutor 每次执行 SQL 新建 Statement,执行后关闭 大多数单条 SQL 场景(默认类型)
REUSE ReuseExecutor 按 SQL 缓存 Statement,复用避免重建 重复执行相同 SQL(如循环查询)
BATCH BatchExecutor 缓存多条 SQL,批量提交 批量插入 / 更新 / 删除(减少网络开销)

Executor 的创建流程

Executor 通过 Configuration.newExecutor() 方法创建,核心逻辑是 “根据 ExecutorType 生成基础执行器,若开启二级缓存则用 CachingExecutor 包装”:

1. 核心源码:Configuration.newExecutor ()

阅读全文 »

ThreadLocal线程本地存储详解

在并发编程中,处理共享数据时通常需要同步机制(如synchronizedLock)来保证线程安全。但 ThreadLocal 提供了另一种思路:让共享数据不再共享,通过为每个线程创建独立的变量副本,实现线程间的数据隔离。

ThreadLocal 核心原理

基本概念

ThreadLocal(线程本地变量)为每个线程维护一个独立的变量副本,线程对副本的修改不会影响其他线程。其核心思想是:

  • 空间换时间:通过为每个线程分配独立内存空间,避免线程间的同步开销。
  • 数据隔离:每个线程操作自己的副本,消除竞争条件。

实现结构

ThreadLocal 的实现依赖于Thread类和ThreadLocalMap

  • Thread 类:每个线程持有两个ThreadLocalMap对象:

    1
    2
    ThreadLocal.ThreadLocalMap threadLocals = null;       // 线程本地变量
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; // 可继承的本地变量
  • ThreadLocalMap:ThreadLocal 的静态内部类,本质是一个哈希表,key 为 ThreadLocal 对象,value 为线程的变量副本

ThreadLocal 核心方法

ThreadLocal 通过以下方法操作线程的变量副本:

get():获取当前线程的变量副本

阅读全文 »

Web 服务器与应用服务器:核心区别与协同架构

在 Web 架构中,Web 服务器与应用服务器是支撑服务运行的两大核心组件,但两者的定位和功能差异显著。本文从定义、功能、典型产品及协同场景入手,详解两者的区别与联系,并结合 Nginx 实战案例说明如何构建高效的服务架构。

Web 服务器:处理 HTTP 请求的 “前端管家”

Web 服务器(Web Server)是专门处理 HTTP/HTTPS 请求的服务器,核心功能是接收客户端请求、返回静态资源(如 HTML、图片、CSS),或通过反向代理将动态请求转发给应用服务器。

核心特性

  • 协议支持:专注于 HTTP/HTTPS 协议,处理请求头解析、响应构建等;
  • 静态资源处理:高效传输静态文件(图片、JS、CSS 等),支持缓存、压缩(如 Gzip);
  • 连接管理:优化 TCP 连接复用(如长连接)、并发处理(如 Nginx 的事件驱动模型);
  • 反向代理:作为中间层转发请求到后端服务,实现负载均衡、动静分离。

典型产品

  • Nginx:轻量高效,支持高并发、反向代理、负载均衡,广泛用于静态资源服务和反向代理;
  • Apache HTTP Server:老牌服务器,模块丰富,兼容性好,但高并发性能弱于 Nginx;
  • IIS:Windows 系统自带服务器,集成.NET 环境;
  • Lighttpd:轻量级服务器,适合嵌入式或低资源场景。

适用场景

  • 托管纯静态网站(如企业官网、静态博客);
  • 作为反向代理,分发请求到应用服务器;
  • 实现负载均衡、SSL 终止(HTTPS 解密)、静态资源缓存。

应用服务器:运行业务逻辑的 “后端引擎”

应用服务器(Application Server)是运行动态业务逻辑的服务器,核心功能是处理动态请求(如用户登录、数据查询)、执行应用程序代码(如 Java、Python),并与数据库交互生成动态内容。

核心特性

  • 动态内容生成:运行服务器端代码(如 Java Servlet、PHP、ASP.NET),生成动态 HTML;
  • 组件支持:提供业务层组件(如事务管理、安全认证、会话管理);
  • 协议多样性:除 HTTP 外,可能支持 RPC、JMS 等协议(如 Java EE 应用服务器);
  • 集群与高可用:原生支持会话共享、集群部署(如 Tomcat 集群、JBoss 集群)。

典型产品

  • Tomcat:轻量级 Java 应用服务器,支持 Servlet/JSP,常与 Nginx 配合使用;
  • JBoss/WildFly:开源 Java EE 应用服务器,支持完整的企业级特性(如 EJB、JPA);
  • WebLogic/WebSphere:商业 Java EE 服务器,适合大型企业级应用;
  • Node.js:JavaScript 运行时,可作为轻量级应用服务器处理动态请求。

适用场景

  • 运行动态 Web 应用(如电商网站、管理系统);
  • 处理复杂业务逻辑(如订单处理、用户认证);
  • 与数据库交互,生成个性化内容。

核心区别与联系

维度 Web 服务器 应用服务器
核心功能 处理 HTTP 请求,传输静态资源 运行动态代码,处理业务逻辑
处理对象 静态资源(HTML、图片等) 动态请求(Servlet、API 调用等)
性能特点 高并发、低延迟,适合 IO 密集型场景 侧重业务处理,适合计算密集型场景
典型协议 HTTP/HTTPS HTTP、RPC、JMS 等
阅读全文 »

MyBatis 别名(TypeAlias)全解析:配置、原理与最佳实践

MyBatis 的别名(TypeAlias)机制是为了简化 XML 映射文件和注解中类全限定名的重复书写,通过简短的别名替代冗长的包名 + 类名(如用 user 替代 com.example.mybatis.model.User),提升配置文件的可读性和开发效率。从 “配置方式→底层原理→常见问题→最佳实践” 四个维度,系统梳理 MyBatis 别名的核心逻辑,帮你彻底掌握别名的使用与优化。

别名的核心价值与适用场景

在理解配置前,先明确别名的核心作用 ——简化配置,降低维护成本

  • 问题场景:若实体类位于较深的包下(如 com.example.mybatis.module.user.model.User),在 resultMapparameterTyperesultType 中重复书写全限定名会非常繁琐,且修改包名时需全局替换;
  • 解决方案:通过别名机制,将全限定名映射为简短名称(如 user),配置更简洁,维护更高效。

适用场景

  1. XML 映射文件中的 resultMaptype 属性)、select/insert 等标签的 parameterType/resultType 属性;
  2. 注解中的类型引用(如 @Result(type = User.class) 可改为 @Result(type = "user"));
  3. 动态 SQL 中的类型判断(如 OGNL 表达式 test="obj instanceof user")。

别名的四种配置方式

MyBatis 支持 XML 单个别名、XML 包扫描、注解配置、默认别名 四种方式,覆盖不同场景的需求,优先级为:注解别名 > XML 单个别名 > XML 包扫描默认别名 > 系统默认别名

1. 方式 1:系统默认别名(无需配置,直接使用)

MyBatis 对 Java 基础类型、常用集合类 预设了默认别名,在 TypeAliasRegistry 的构造函数中初始化,可直接在配置中使用,无需额外配置。

常用默认别名对照表
别名(不区分大小写) 对应的 Java 类型 说明
string java.lang.String 字符串类型
int/integer java.lang.Integer 整数类型(_int 对应 int 基本类型)
long java.lang.Long 长整型(_long 对应 long 基本类型)
date java.util.Date 日期类型
decimal/bigdecimal java.math.BigDecimal 高精度小数类型
map java.util.Map Map 接口
hashmap java.util.HashMap HashMap 实现类
list java.util.List List 接口
arraylist java.util.ArrayList ArrayList 实现类
使用示例
阅读全文 »