深入解析MyBatis中#{}与${}的区别:从源码角度揭秘底层实现原理

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 【4月更文挑战第20天】

MyBatis作为一款优秀的持久层框架,广泛应用于Java项目中。在使用MyBatis时,我们经常会遇到#{}${}这两种参数绑定方式。虽然它们看起来类似,但实际上在使用和处理上有着根本的不同。本文将从源码的角度深入解析MyBatis中#{}${}的区别,探究其底层实现原理,帮助读者更加深入地理解MyBatis的工作机制。

#{}${}的基本概念

在MyBatis中,#{}${}都用于参数绑定,但它们的处理方式有所不同:

  • #{}用于预编译,可以防止SQL注入攻击,通常用于动态拼接SQL语句中的值。
  • ${}直接替换成相应的参数值,可以用于动态拼接SQL语句中的列名、表名等不需要预编译的部分。

#{}${}的区别

1. SQL注入防范

  • #{}:使用#{}可以防范SQL注入攻击,因为MyBatis会将参数值进行预编译,将其作为SQL语句的参数传入,而不是直接将参数值拼接到SQL语句中。
  • ${}:使用${}时,参数值会直接替换SQL语句中的${}占位符,存在SQL注入的风险,尤其是当参数值来自用户输入时,应谨慎使用${}

2. 数据类型转换

  • #{}:MyBatis会根据参数值的数据类型自动进行转换,例如将Java中的String类型转换为数据库中的VARCHAR类型。
  • ${}${}不进行数据类型转换,直接将参数值按字符串拼接到SQL语句中,需要保证参数值的类型与SQL语句的要求一致。

3. 预编译

  • #{}#{}是预编译的,MyBatis会将#{}替换成占位符,并将参数值作为预编译语句的参数传入,从而提高了SQL语句的执行效率。
  • ${}${}不是预编译的,MyBatis会直接将${}替换成参数值,拼接到SQL语句中,可能导致SQL语句的重复编译和执行,影响性能。

#{}${}的底层实现原理

1. #{}的处理过程

  • MyBatis会将#{}替换成占位符,例如?
  • 将参数值作为预编译语句的参数传入。

2. ${}的处理过程

  • MyBatis会直接将${}替换成参数值,拼接到SQL语句中。

3. 源码解析

MyBatis核心组件

1. Configuration

Configuration是MyBatis的核心配置类,负责解析和管理MyBatis的配置信息,包括数据库连接信息、映射器配置、缓存配置等。在MyBatis的初始化过程中,会创建一个全局唯一的Configuration对象,用于保存整个应用的配置信息。

2. SqlSessionFactory

SqlSessionFactory是MyBatis的工厂类,用于创建SqlSession对象。在MyBatis的初始化过程中,会根据Configuration对象创建一个全局唯一的SqlSessionFactory实例,用于产生SqlSession对象。

3. SqlSession

SqlSession是MyBatis的核心会话类,负责与数据库进行交互。SqlSession提供了多种方法用于执行SQL语句、获取映射器接口实例、管理事务等操作。

4. MapperProxy

MapperProxy是MyBatis的动态代理类,用于生成映射器接口的代理对象。当调用映射器接口方法时,MapperProxy会拦截方法调用,并将其转发给SqlSession执行相应的SQL语句。

MyBatis关键流程

1. 初始化过程

MyBatis的初始化过程包括解析配置文件、创建SqlSessionFactory、加载映射器文件等步骤。在初始化过程中,MyBatis会读取配置文件中的信息,并根据配置信息创建相应的对象。

2. SQL语句处理流程

SQL语句处理流程包括SQL语句的解析、参数绑定、SQL语句的执行等步骤。在执行SQL语句时,MyBatis会根据映射器接口的方法名查找相应的SQL语句,并将参数绑定到SQL语句中,最终执行SQL语句并返回结果。

3. 缓存机制

MyBatis提供了一级缓存和二级缓存两种缓存机制,用于提高SQL查询的性能。一级缓存是SqlSession级别的缓存,二级缓存是Mapper级别的缓存。MyBatis会根据配置信息自动管理缓存的生命周期,并在需要时自动更新缓存中的数据。

深入源码解析

1. Configuration源码解析
public class Configuration {
   
   
    // 配置信息
    private Properties properties = new Properties();
    // 数据源信息
    private DataSource dataSource;
    // 映射器配置信息
    private final MapperRegistry mapperRegistry = new MapperRegistry(this);
    // 其他配置信息...

    // 初始化方法
    public Configuration() {
   
   
        // 加载配置文件
        properties.load(Resources.getResourceAsStream("mybatis-config.xml"));
        // 解析配置信息...
    }

    // 其他方法...
}
2. SqlSessionFactory源码解析
public class SqlSessionFactory {
   
   
    // 配置信息
    private Configuration configuration;

    // 构造方法
    public SqlSessionFactory(Configuration configuration) {
   
   
        this.configuration = configuration;
    }

    // 创建SqlSession对象
    public SqlSession openSession() {
   
   
        return new DefaultSqlSession(configuration);
    }

    // 其他方法...
}
3. SqlSession源码解析
public class SqlSession {
   
   
    // 配置信息
    private Configuration configuration;
    // 数据库连接
    private Connection connection;

    // 构造方法
    public SqlSession(Configuration configuration) {
   
   
        this.configuration = configuration;
        this.connection = configuration.getDataSource().getConnection();
    }

    // SQL语句执行方法
    public <T> T selectOne(String statement, Object parameter) {
   
   
        // 解析SQL语句、参数绑定、执行SQL语句...
    }

    // 其他方法...
}

如何选择合适的参数绑定方式?

  • 当参数值来自用户输入,且需要防范SQL注入攻击时,应使用#{}
  • 当参数值不需要预编译,且不涉及SQL注入风险时,可以考虑使用${},但需要确保参数值的类型与SQL语句的要求一致。

总结

通过本文的详细介绍,读者对于MyBatis中#{}${}的区别以及底层实现原理有了更深入的理解。#{}${}在使用和处理上有着根本的不同,开发人员在编写SQL语句时应根据实际情况选择合适的参数绑定方式,以提高系统的性能和安全性。深入了解MyBatis的工作机制,有助于开发人员更好地利用MyBatis进行持久化操作,提高开发效率和代码质量。

目录
相关文章
|
6天前
|
前端开发 Java 应用服务中间件
21张图解析Tomcat运行原理与架构全貌
【10月更文挑战第2天】本文通过21张图详细解析了Tomcat的运行原理与架构。Tomcat作为Java Web开发中最流行的Web服务器之一,其架构设计精妙。文章首先介绍了Tomcat的基本组件:Connector(连接器)负责网络通信,Container(容器)处理业务逻辑。连接器内部包括EndPoint、Processor和Adapter等组件,分别处理通信、协议解析和请求封装。容器采用多级结构(Engine、Host、Context、Wrapper),并通过Mapper组件进行请求路由。文章还探讨了Tomcat的生命周期管理、启动与停止机制,并通过源码分析展示了请求处理流程。
|
18小时前
|
Java Spring
Spring底层架构源码解析(三)
Spring底层架构源码解析(三)
|
1天前
|
存储 Java API
从源码角度解析ArrayList.subList的几个坑!
从源码角度解析ArrayList.subList的几个坑!
|
3天前
|
开发框架 缓存 前端开发
electron-builder 解析:你了解其背后的构建原理吗?
本文首发于微信公众号“前端徐徐”,详细解析了 electron-builder 的工作原理。electron-builder 是一个专为整合前端项目与 Electron 应用的打包工具,负责管理依赖、生成配置文件及多平台构建。文章介绍了前端项目的构建流程、配置信息收集、依赖处理、asar 打包、附加资源准备、Electron 打包、代码签名、资源压缩、卸载程序生成、安装程序生成及最终安装包输出等环节。通过剖析 electron-builder 的原理,帮助开发者更好地理解和掌握跨端桌面应用的构建流程。
16 2
|
18小时前
|
XML Java 数据格式
Spring底层架构源码解析(二)
Spring底层架构源码解析(二)
|
1天前
|
算法 Java 程序员
Map - TreeSet & TreeMap 源码解析
Map - TreeSet & TreeMap 源码解析
7 0
|
1天前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
11 0
|
1天前
|
算法 Java 容器
Map - HashSet & HashMap 源码解析
Map - HashSet & HashMap 源码解析
8 0
|
1天前
|
存储 Java C++
Collection-PriorityQueue源码解析
Collection-PriorityQueue源码解析
7 0
|
1天前
|
安全 Java 程序员
Collection-Stack&Queue源码解析
Collection-Stack&Queue源码解析
7 0

推荐镜像

更多