0%

MyBatis SQL 节点解析:从 SqlSource 到 BoundSql 的完整流程

MyBatis 中 SQL 节点(<select>/<insert>等)的解析是 SQL 执行的基础环节。从 Mapper 配置文件中的 SQL 文本,到最终可执行的数据库语句,中间经历了 “SQL 节点→SqlSource→BoundSql” 的转换过程。本文将深入解析SqlSource接口及其实现类的职责,以及BoundSql的核心作用,揭示 MyBatis 处理静态与动态 SQL 的底层逻辑。

SqlSource:SQL 语句的 “源容器”

SqlSource是 MyBatis 中封装 SQL 语句及其解析逻辑的接口,它的核心职责是根据传入的参数对象,生成可执行的BoundSql对象(包含最终 SQL、参数映射等信息)。

SqlSource 接口定义

1
2
3
4
public interface SqlSource {
// 根据参数对象,生成包含最终SQL和参数映射的BoundSql
BoundSql getBoundSql(Object parameterObject);
}

SqlSource的关键作用是隔离 SQL 的静态结构与动态解析逻辑:无论是静态 SQL(无动态标签)还是动态 SQL(含<if>/<foreach>等),都通过统一的getBoundSql方法提供可执行的 SQL 信息,简化了后续执行器(Executor)的处理逻辑。

SqlSource 的四大实现类:分工与场景

MyBatis 提供 4 种SqlSource实现类,分别对应不同类型的 SQL 定义(静态 / 动态 / 注解提供等),形成了完整的 SQL 解析体系。

1. DynamicSqlSource:动态 SQL 的解析器

核心职责:处理包含动态标签(<if>/<when>/<foreach>/<trim>等)的 SQL 语句,需要根据参数动态生成最终 SQL。

适用场景:
  • 包含动态逻辑的 SQL(如 “根据条件拼接查询条件”):

阅读全文 »

MyBatis 中的 OGNL 表达式:从基础语法到实战应用

在 MyBatis 的 XML 映射文件(如动态 SQL、结果映射)中,OGNL(Object-Graph Navigation Language,对象图导航语言)是核心表达式语言,负责解析参数、判断条件、导航对象属性。本文将系统梳理 OGNL 表达式在 MyBatis 中的基础语法、核心用法及常见场景,帮助你灵活编写动态 SQL 和处理复杂参数映射。

OGNL 表达式的核心作用

OGNL 是一种强大的表达式语言,支持对象属性导航、方法调用、集合操作、逻辑运算等功能。在 MyBatis 中,OGNL 主要用于以下场景:

  1. 动态 SQL 条件判断ifwhen 标签的 test 属性(如 test="name != null and name != ''");
  2. 参数取值与转换#{}占位符的参数解析(如 #{user.name} 导航对象属性);
  3. 结果映射与计算resultMap 中的 select 属性、bind 标签的变量定义(如 value="'%' + name + '%'");
  4. 内置对象引用:访问 MyBatis 内置参数(如 _parameter_databaseId)。

OGNL 基础语法(MyBatis 常用)

OGNL 语法简洁但功能强大,以下是 MyBatis 开发中高频使用的语法规则:

1. 基本数据类型与字面量

类型 示例 说明
字符串 'hello'"world" 单引号或双引号包裹,支持转义字符(如 'a\'b'
数值 1003.14-5 整数、浮点数直接书写
布尔值 truefalse 注意小写,区分 Java 的 True/False
空值 null 判断参数是否为空(如 test="name == null"

2. 对象属性导航

OGNL 支持通过.符号导航对象的多层属性,即使属性是嵌套对象也能直接访问。

示例:参数为复杂对象

假设有实体类 User

阅读全文 »

Spring 自定义属性编辑器:从原理到实战

在 Spring 中,属性编辑器(Property Editor)负责将配置文件中的字符串值转换为对应的数据类型(如将 "2023-10-01" 转换为 Date 对象)。Spring 内置了多种编辑器(如处理集合、日期的编辑器),但在复杂场景下(如自定义对象转换),需要我们实现自定义属性编辑器。本文将详细讲解自定义属性编辑器的实现步骤、底层原理及实战案例。

属性编辑器的核心作用

Spring 在解析 Bean 配置时,XML 或注解中的属性值都是字符串类型(如 <property name="birthday" value="2023-10-01"/> 中的 "2023-10-01"),而目标 Bean 的属性可能是 DateUser 等复杂类型。

属性编辑器的作用是:将字符串形式的属性值转换为目标数据类型,是 Spring 类型转换体系的核心组件。

Spring 内置属性编辑器

Spring 已默认注册了多种常用属性编辑器(通过 BeanWrapperImpl 实现),覆盖大部分基础类型转换:

编辑器类名 功能描述 示例(字符串→目标类型)
CustomDateEditor 字符串与 Date 转换 "2023-10-01"new Date(2023,9,1)
CustomCollectionEditor 字符串与集合(List/Set)转换 "1,2,3"List.of(1,2,3)
CustomMapEditor 字符串与 Map 转换 "name:张三,age:20"Map 对象
ByteArrayPropertyEditor 字符串与字节数组转换 "hello"byte[] {104,101,108,108,111}
ClassEditor 类名与 Class 对象转换 "java.lang.String"String.class

若内置编辑器无法满足需求(如自定义 User 对象转换),则需要自定义属性编辑器。

自定义属性编辑器的实现步骤

自定义属性编辑器需遵循以下步骤,核心是通过 CustomEditorConfigurerBeanFactoryPostProcessor 实现类)向 Spring 注册编辑器。

阅读全文 »

Spring Boot 热部署详解:从 Tomcat 配置到 Spring Boot 专属方案

热部署(Hot Deployment)是指在应用不停止运行的前提下,自动或手动加载修改后的代码 / 资源,避免频繁重启应用,大幅提升开发效率。传统 Tomcat 热部署需手动配置,而 Spring Boot 提供了更简洁的专属方案(spring-boot-devtoolsspringloaded)。从 “传统 Tomcat 热部署配置→Spring Boot 热部署方案→原理与注意事项” 三个维度,系统讲解热部署的实现方法与最佳实践,帮你高效开发 Spring Boot 应用。

热部署 vs 热加载:概念辨析

在讲解具体方案前,需先明确 “热部署” 与 “热加载” 的区别(避免混淆):

特性 热部署(Hot Deployment) 热加载(Hot Swapping)
核心原理 重新部署整个应用(销毁旧的 ClassLoader,创建新的) 仅替换修改的类 / 资源(不销毁整个 ClassLoader)
适用范围 所有代码 / 资源修改(包括配置文件、依赖) 仅支持类文件修改(不支持配置文件、依赖变更)
性能 耗时较长(需重启应用上下文) 耗时极短(仅加载修改的类)
实现工具 Tomcat 配置、Spring Boot DevTools(部分场景) JRebel、Spring Loaded、JVM HotSwap

本文中 “热部署” 为广义概念,包含上述两种场景,重点讲解 Spring Boot 开发中常用的高效方案。

传统 Tomcat 热部署配置(非 Spring Boot 专属)

若需在外置 Tomcat(非 Spring Boot 内置容器)中实现热部署,需通过配置 Tomcat 关联项目,核心是开启 reloadable="true"(自动检测项目变更并重启)。三种方式本质是 “项目与 Tomcat 的关联方式”,具体如下:

方式一:直接将项目放入 Tomcat 的 webapps 目录

这是最简单的方式,无需额外配置,适合快速测试:

阅读全文 »

Web 存储(localStorage & sessionStorage)详解:用法、区别与实战指南

Web 存储是浏览器提供的客户端数据存储方案,通过键值对(Key-Value)形式将数据保存在用户本地,仅允许存储该数据的网页(同源页面)访问,无需与服务器交互,适用于 “临时状态保存”“用户偏好设置”“离线数据缓存” 等场景。Web 存储主要分为 localStorage(本地存储)sessionStorage(会话存储) 两种,二者 API 相似但生命周期、作用范围差异显著。从 “核心区别→API 详解→实战场景→注意事项” 四个维度,全面讲解 Web 存储的使用方法与最佳实践

localStorage 与 sessionStorage 核心区别

在学习具体用法前,需先明确二者的核心差异,避免使用场景混淆:

对比维度 localStorage sessionStorage
数据生命周期 永久存储,无过期时间(除非手动删除或清除浏览器数据) 临时存储,仅在当前窗口 / 标签页生命周期内有效(关闭窗口 / 标签页后自动删除)
作用范围 同源页面共享(同一协议、域名、端口的所有窗口 / 标签页) 仅当前窗口 / 标签页独立(即使同源,新窗口 / 标签页也无法访问)
存储容量 约 5MB(不同浏览器略有差异,无统一标准) 约 5MB(与 localStorage 一致)
数据持久化 浏览器重启、设备重启后数据仍保留 窗口关闭或浏览器重启后数据丢失
适用场景 用户偏好设置(如主题、语言)、长期离线数据缓存 临时表单数据(如未提交的表单内容)、页面间临时状态传递

localStorage 详解:永久本地存储

localStorage 用于长久保存同源页面的共享数据,数据存储在浏览器的本地文件中(不同浏览器存储位置不同),除非手动删除,否则会一直保留(即使关闭浏览器、重启设备)。

1. 核心 API

localStorage 是 window 对象的属性,所有 API 均为同步操作(执行时会阻塞后续代码,需注意避免大量数据操作):

阅读全文 »