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

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【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进行持久化操作,提高开发效率和代码质量。

目录
相关文章
|
27天前
|
监控 网络协议 算法
OSPFv2与OSPFv3的区别:全面解析与应用场景
OSPFv2与OSPFv3的区别:全面解析与应用场景
33 0
|
2天前
|
存储 缓存 算法
HashMap深度解析:从原理到实战
HashMap,作为Java集合框架中的一个核心组件,以其高效的键值对存储和检索机制,在软件开发中扮演着举足轻重的角色。作为一名资深的AI工程师,深入理解HashMap的原理、历史、业务场景以及实战应用,对于提升数据处理和算法实现的效率至关重要。本文将通过手绘结构图、流程图,结合Java代码示例,全方位解析HashMap,帮助读者从理论到实践全面掌握这一关键技术。
30 13
|
21天前
|
运维 持续交付 云计算
深入解析云计算中的微服务架构:原理、优势与实践
深入解析云计算中的微服务架构:原理、优势与实践
55 1
|
1月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
71 2
|
15天前
|
PyTorch Shell API
Ascend Extension for PyTorch的源码解析
本文介绍了Ascend对PyTorch代码的适配过程,包括源码下载、编译步骤及常见问题,详细解析了torch-npu编译后的文件结构和三种实现昇腾NPU算子调用的方式:通过torch的register方式、定义算子方式和API重定向映射方式。这对于开发者理解和使用Ascend平台上的PyTorch具有重要指导意义。
|
19天前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
50 12
|
1月前
|
SQL Java 数据库连接
Mybatis架构原理和机制,图文详解版,超详细!
MyBatis 是 Java 生态中非常著名的一款 ORM 框架,在一线互联网大厂中应用广泛,Mybatis已经成为了一个必会框架。本文详细解析了MyBatis的架构原理与机制,帮助读者全面提升对MyBatis的理解和应用能力。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Mybatis架构原理和机制,图文详解版,超详细!
|
21天前
|
Java 编译器 API
深入解析:JDK与JVM的区别及联系
在Java开发和运行环境中,JDK(Java Development Kit)和JVM(Java Virtual Machine)是两个核心概念,它们在Java程序的开发、编译和运行过程中扮演着不同的角色。本文将深入解析JDK与JVM的区别及其内在联系,为Java开发者提供清晰的技术干货。
23 1
|
29天前
|
运维 持续交付 虚拟化
深入解析Docker容器化技术的核心原理
深入解析Docker容器化技术的核心原理
45 1
|
1月前
|
存储 安全 Linux
Golang的GMP调度模型与源码解析
【11月更文挑战第11天】GMP 调度模型是 Go 语言运行时系统的核心部分,用于高效管理和调度大量协程(goroutine)。它通过少量的操作系统线程(M)和逻辑处理器(P)来调度大量的轻量级协程(G),从而实现高性能的并发处理。GMP 模型通过本地队列和全局队列来减少锁竞争,提高调度效率。在 Go 源码中,`runtime.h` 文件定义了关键数据结构,`schedule()` 和 `findrunnable()` 函数实现了核心调度逻辑。通过深入研究 GMP 模型,可以更好地理解 Go 语言的并发机制。

推荐镜像

更多