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

简介: 【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进行持久化操作,提高开发效率和代码质量。

目录
相关文章
|
4月前
|
Java 数据库连接 API
Java 对象模型现代化实践 基于 Spring Boot 与 MyBatis Plus 的实现方案深度解析
本文介绍了基于Spring Boot与MyBatis-Plus的Java对象模型现代化实践方案。采用Spring Boot 3.1.2作为基础框架,结合MyBatis-Plus 3.5.3.1进行数据访问层实现,使用Lombok简化PO对象,MapStruct处理对象转换。文章详细讲解了数据库设计、PO对象实现、DAO层构建、业务逻辑封装以及DTO/VO转换等核心环节,提供了一个完整的现代化Java对象模型实现案例。通过分层设计和对象转换,实现了业务逻辑与数据访问的解耦,提高了代码的可维护性和扩展性。
167 1
|
3月前
|
SQL Java 数据库连接
Spring、SpringMVC 与 MyBatis 核心知识点解析
我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。 在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。 SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。 MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态
118 0
|
6月前
|
SQL 存储 Java
Mybatis源码解析:详述初始化过程
以上就是MyBatis的初始化过程,这个过程主要包括SqlSessionFactory的创建、配置文件的解析和加载、映射文件的加载、SqlSession的创建、SQL的执行和SqlSession的关闭。这个过程涉及到了MyBatis的核心类和接口,包括SqlSessionFactory、SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、Configuration、SqlSession和Executor等。通过这个过程,我们可以看出MyBatis的灵活性和强大性,它可以很好地支持定制化SQL、存储过程以及高级映射,同时也避免了几
110 20
|
7月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
658 29
|
7月前
|
机器学习/深度学习 数据可视化 PyTorch
深入解析图神经网络注意力机制:数学原理与可视化实现
本文深入解析了图神经网络(GNNs)中自注意力机制的内部运作原理,通过可视化和数学推导揭示其工作机制。文章采用“位置-转移图”概念框架,并使用NumPy实现代码示例,逐步拆解自注意力层的计算过程。文中详细展示了从节点特征矩阵、邻接矩阵到生成注意力权重的具体步骤,并通过四个类(GAL1至GAL4)模拟了整个计算流程。最终,结合实际PyTorch Geometric库中的代码,对比分析了核心逻辑,为理解GNN自注意力机制提供了清晰的学习路径。
494 7
深入解析图神经网络注意力机制:数学原理与可视化实现
|
7月前
|
传感器 人工智能 监控
反向寻车系统怎么做?基本原理与系统组成解析
本文通过反向寻车系统的核心组成部分与技术分析,阐述反向寻车系统的工作原理,适用于适用于商场停车场、医院停车场及火车站停车场等。如需获取智慧停车场反向寻车技术方案前往文章最下方获取,如有项目合作及技术交流欢迎私信作者。
460 2
|
7月前
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
191 4
|
7月前
|
Java 关系型数据库 数据库连接
Javaweb之Mybatis入门程序的详细解析
本文详细介绍了一个MyBatis入门程序的创建过程,从环境准备、Maven项目创建、MyBatis配置、实体类和Mapper接口的定义,到工具类和测试类的编写。通过这个示例,读者可以了解MyBatis的基本使用方法,并在实际项目中应用这些知识。
165 11
|
7月前
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
7月前
|
SQL 缓存 Java
框架源码私享笔记(02)Mybatis核心框架原理 | 一条SQL透析核心组件功能特性
本文详细解构了MyBatis的工作机制,包括解析配置、创建连接、执行SQL、结果封装和关闭连接等步骤。文章还介绍了MyBatis的五大核心功能特性:支持动态SQL、缓存机制(一级和二级缓存)、插件扩展、延迟加载和SQL注解,帮助读者深入了解其高效灵活的设计理念。

推荐镜像

更多
  • DNS