深入解析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进行持久化操作,提高开发效率和代码质量。

目录
相关文章
|
5天前
|
存储 芯片
【期末不挂科-单片机考前速过系列P11】(第十一章:15题速过串行口的工作原理和应用)经典例题盘点(带图解析)
【期末不挂科-单片机考前速过系列P11】(第十一章:15题速过串行口的工作原理和应用)经典例题盘点(带图解析)
【期末不挂科-单片机考前速过系列P10】(第十章:11题中断系统的工作原理及应用)经典例题盘点(带图解析)
【期末不挂科-单片机考前速过系列P10】(第十章:11题中断系统的工作原理及应用)经典例题盘点(带图解析)
|
5天前
|
C语言 C++
【期末不挂科-单片机考前速过系列P1】(第一章:27题搞定单片机&其工作原理)经典例题盘点【选择题&判断题&填空题】(带图解析)
【期末不挂科-单片机考前速过系列P1】(第一章:27题搞定单片机&其工作原理)经典例题盘点【选择题&判断题&填空题】(带图解析)
|
6天前
|
SQL Java 数据库连接
一文细说Mybatis八大核心源码
以上 是V哥给大家整理的8大核心组件的全部内容,为什么说选择 Java 就是选择未来,真正爱 Java 的人,一定喜欢深入研究,学习源码只是第一步,要有一杆子捅到操作系统才够刺激。
|
6天前
|
JavaScript 前端开发 算法
vue生命周期函数原理解析,vue阻止事件冒泡方法实现
vue生命周期函数原理解析,vue阻止事件冒泡方法实现
|
6天前
|
缓存 Java 开发者
10个点介绍SpringBoot3工作流程与核心组件源码解析
Spring Boot 是Java开发中100%会使用到的框架,开发者不仅要熟练使用,对其中的核心源码也要了解,正所谓知其然知其所以然,V 哥建议小伙伴们在学习的过程中,一定要去研读一下源码,这有助于你在开发中游刃有余。欢迎一起交流学习心得,一起成长。
|
6天前
|
芯片
EDA设计:原理、实践与代码深度解析
EDA设计:原理、实践与代码深度解析
16 2
|
6天前
|
算法 计算机视觉 Python
DSP技术深度解析:原理、实践与应用
DSP技术深度解析:原理、实践与应用
14 1
|
7天前
|
安全 网络协议 Java
Netty核心NioEventLoop源码解析(下)
Netty核心NioEventLoop源码解析(下)
20 0
|
7天前
|
算法 Java 索引
Netty核心NioEventLoop源码解析(上)
Netty核心NioEventLoop源码解析(上)
20 0

推荐镜像

更多