商城首页欢迎来到中国正版软件门户

您的位置:首页 >MyBatis XML开发全面完整指南

MyBatis XML开发全面完整指南

  发布于2026-08-06 阅读(0)

扫一扫,手机访问

前期回顾:

MyBatis的开发有两种方式:

1.注解

2.XML

上一小节,我们聊了注解方式,这一节再来看XML方式。简单来说,注解适合快速搞定简单的增删改查,但一旦涉及复杂SQL逻辑,XML配置文件才是真正的利器——把SQL语句写在XML里,维护起来清晰得多。

一、MyBatis XML配置文件

用XML方式,主要完成两步:

  1. 配置数据库连接信息和MyBatis基础设置
  2. 写持久层代码

1.1 配置数据库连接信息和MyBatis基础设置

application.yml配置:

# 数据库连接配置
spring:
  datasource:
  url: jdbc:mysql://127.0.0.1:3306/mybatis_test?
  characterEncoding=utf8&useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
#配置mybatis xml的文件路径,在resources/mapper创建所有表的xml文件
mybatis:
  mapper-locations:classpath:mapper/**Mapper.xml

application.properties配置:

#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库链接的url
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatis_test?
characterEncoding=utf8&useSSL=false
#连接数据库的用户名
spring.datasource.username=root
#链接数据库的密码
spring.datasource.password=root
#配置mybatis xml文件路径,在resources/mapper创建所有表的xml文件
mybatis.mapper-locations=classpath:mapper/**Mapper.xml

1.2 写持久层代码

持久层代码分两部分:

  1. 方法定义:Interface
  2. 方法实现:XXX.xml

MyBatis XML开发全面完整指南

1.2.1 添加mapper接口

先加一个插件:

MyBatis XML开发全面完整指南

数据持久层的定义接口:

package com.MybatisDemo.demo.mapper;
import com.MybatisDemo.demo.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;
import ja va.util.List;
@Mapper
public interface UserInfoXMLMapper {
List queryAllUser();
}

1.2.2 添加UserInfoXMLMapper.xml



//这里的namespace根据实际情况写

创建UserInfoXMLMapper.xml,路径参考properties/yml中的配置

MyBatis XML开发全面完整指南

查询所有用户的具体实现:

  • 光标对准queryAllUser方法名,然后alt+enter键,点击Generate statement

MyBatis XML开发全面完整指南

将自动生成:

MyBatis XML开发全面完整指南

  • 标签中写入sql语句:

select username,`password`,age,gender,phone from user_info

  • 单元测试
@SpringBootTest
class UserInfoXMLMapperTest {
    @Autowired
    private UserInfoXMLMapper userInfoXMLMapper;
    @Test
    void queryAllUser(){
        List userInfoXMLList =userInfoXMLMapper.queryAllUser();
        System.out.println(userInfoXMLList);
    }
}
  • 运行展示

MyBatis XML开发全面完整指南

以上是具体操作,接下来对标签进行说明

MyBatis XML开发全面完整指南

  • 标签:需要指定 namespace 属性,表示命名空间,值为 mapper 接口的全限定名,包括全包名.类名。
  • 标签,这在上一节已初步接触。这里补充更详细的用法和参数传递。

    Mapper 接口方法定义(带参数查询):

    // 根据用户名查询用户
    UserInfo selectUserByName(String username);

    XML 映射配置:

    运行展示:

    MyBatis XML开发全面完整指南

    解决方法和类注解类似:

    1.起别名

    2.结果映射

    3.开启驼峰命名

    其中1,3的解决方法和注解一样,感兴趣的可以看上一篇文章,接下来介绍xml中的结果映射

    
        
        
        
        
    
    

    通过 XML 配置 SQL,使得 SQL 语句与 Ja va 代码分离,结构更清晰,尤其便于维护复杂的动态 SQL

    三、其他查询操作

    3.1 多表查询

    多表查询和单表查询类似,只是sql不同而已

    数据准备:

    DROP TABLE IF EXISTS articleinfo;
    CREATE TABLE articleinfo (
     id INT PRIMARY KEY auto_increment,
     title VARCHAR ( 100 ) NOT NULL,
     content TEXT NOT NULL,
     uid INT NOT NULL,
     delete_flag TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
     create_time DATETIME DEFAULT now(),
     update_time DATETIME DEFAULT now() 
    ) DEFAULT charset 'utf8mb4';
    //插入测试数据
    INSERT INTO articleinfo ( title, content, uid ) VALUES ( 'Ja va', 'Ja va正文', 1);

    数据查询 需求: 根据uid查询作者的名称等相关信息:

    select ta.id,ta.title,ta.content,ta.uid,tb.username,tb.age,tb.gender 
    from articleinfo ta 
    left join user_info tb 
    on ta.uid = tb.id 
    where ta.id =1

    对应model:

    @Data
    public class ArticleInfo {
        private Integer id;
        private String title;
        private String content;
        private Integer uid;
        private Integer deleteFlag;
        private Date createTime;
        private Date updateTime;
        //⽤⼾相关信息
        private String username;
        private Integer age;
        private Integer gender;
    }

    接口定义:

    @Mapper
    public interface ArticleInfoMapper {
         @Select("SELECT ta.id,ta.title,ta.content,ta.uid,tb.username,tb.age,tb.gender " + "FROM articleinfo ta LEFT JOIN user_info tb ON ta.uid = tb.id " + "WHERE ta.id = #{id}") ArticleInfo queryUserByUid(Integer id);}

    3.2 #{} 和 ${}

    3.2.1 #{} 和 ${} 使用

    • 先看Interger类型的参数

    #{} 的使用示例:

      @Select("select username, password, age, gender, phone from user_info where id = #{id}")
        UserInfo queryById(Integer id);

    MyBatis XML开发全面完整指南

    我们发现我们输入的参数并没有在后面拼接,id值使用 ?进行占位,这中sql我们称为“预编译sql”

    ${} 的使用示例:

      @Select("select username, password, age, gender, phone from user_info where id = ${id}")
        UserInfo queryById(Integer id);

    MyBatis XML开发全面完整指南

    • 看String类型的参数

    #{} 的使用示例:

        @Select("select username, password, age, gender, phone from user_info where username = #{name}")
        UserInfo queryByname(String name);

    MyBatis XML开发全面完整指南

    ${} 的使用示例:

        @Select("select username, password, age, gender, phone from user_info where username = ${name}")
        UserInfo queryByname(String name);

    MyBatis XML开发全面完整指南

    可以看到,这次参数依然是直接拼接在sql语句中了,但是字符串作为参数,需要添加单引号,使用${ }不会拼接引号,导致程序报错

    修改代码为:

    @Select("select username, password, age, gender, phone from user_info where username = '${name}'")
        UserInfo queryByname(String name);

    MyBatis XML开发全面完整指南

    从上面例子可以看出:

    #{} 使用的是预编译SQL, 通过 ? 占位的⽅式, 提前对SQL进行编译, 然后把参数填充到SQL语句中. #{} 会根据参数类型, ⾃动拼接引号 '' . ${} 会直接进行字符替换, ⼀起对SQL进行编译. 如果参数为字符串, 需要加上引号 '' . 参数为数字类型时, 也可以加上, 查询结果不变, 但是可能会导致索引失效, 性能下降.

    3.2.2 #{} 和 ${} 区别

    1. 处理方式不同:#{} 采用预编译处理,而 ${} 是字符串直接替换。
    2. 安全性差异:#{} 可以有效防止 SQL 注入攻击,而 ${} 存在 SQL 注入的风险。在查询语句中,虽然可以使用 ${},但通常推荐使用 #{}。
    3. 适用场景:在某些特定场景下,#{} 无法满足需求,例如:
      • 排序功能(ORDER BY 子句)
      • 表名作为参数时
      • 字段名作为参数时
      这些情况需要使用 ${}。
    4. 模糊查询处理:虽然 ${} 可以完成模糊查询,但由于存在 SQL 注入风险,通常建议使用 MySQL 内置的 CONCAT() 函数配合 #{} 来实现:
    
    

    总结:在大多数情况下,应优先使用 #{} 以确保安全性;只有在需要动态指定表名、字段名或排序方式等特殊场景下,才考虑使用 ${},并确保参数来源可信。

    3.3 排序功能

    在 MyBatis 中实现动态排序功能时,由于 #{} 会对参数进行预编译处理并添加引号,导致 SQL 语句语法错误,因此需要使用 ${} 来实现。

    Mapper 接口方法定义:

    // 根据指定字段排序查询用户列表
    List selectUsersOrderBy(@Param("orderField") String orderField, @Param("orderType") String orderType);

    XML 映射配置:

    测试方法:

    @Test
    void testSelectUsersOrderBy() {
        // 按年龄降序排列
        List users = userInfoXMLMapper.selectUsersOrderBy("age", "DESC");
        users.forEach(System.out::println);
    // 按创建时间升序排列
    List users2 = userInfoXMLMapper.selectUsersOrderBy("create_time", "ASC");
    users2.forEach(System.out::println);
    }

    安全注意事项:

    • 使用 ${} 时,必须确保参数值来自可信来源,避免用户直接输入
    • 可以在业务层对排序字段和排序类型进行白名单验证
    • 建议提供固定的排序选项供用户选择,而不是完全开放输入

    3.4 like查询

    在 MyBatis 中进行模糊查询时,虽然可以使用 ${},但由于安全考虑,推荐使用 #{} 配合 MySQL 的 CONCAT() 函数来实现。

    Mapper 接口方法定义:

    // 根据用户名模糊查询
    List selectUsersLikeName(@Param("keyword") String keyword);

    XML 映射配置(安全写法):

    XML 映射配置(不安全写法 - 不推荐):

    
    

    测试方法:

    @Test
    void testSelectUsersLikeName() {
        // 查询包含"张"字的用户
        List users = userInfoXMLMapper.selectUsersLikeName("张");
        System.out.println("查询结果数量:" + users.size());
        users.forEach(System.out::println);
    // 查询包含"admin"的用户
    List users2 = userInfoXMLMapper.selectUsersLikeName("admin");
    System.out.println("查询结果数量:" + users2.size());
    }

    其他模糊查询模式:

    • 左模糊: LIKE CONCAT('%', #{keyword})
    • 右模糊: LIKE CONCAT(#{keyword}, '%')
    • 全模糊: LIKE CONCAT('%', #{keyword}, '%')(如上例)

    性能优化建议:

    • 对于大数据表的模糊查询,建议添加合适的索引
    • 避免在模糊查询条件前使用通配符 %,这会导致索引失效
    • 考虑使用全文索引(FULLTEXT)替代 LIKE 查询,提高查询效率

    四、数据库连接池

    4.1 介绍

    数据库连接池(Database Connection Pool)是一种用于管理数据库连接的技术,它在应用程序启动时创建一定数量的数据库连接,并将这些连接保存在一个"池"中。当应用程序需要访问数据库时,从连接池中获取一个空闲连接,使用完毕后归还给连接池,而不是直接关闭连接。

    数据库连接池的主要优势:

    • 提高性能:避免了频繁创建和销毁连接的开销
    • 资源复用:连接可以被多个请求重复使用
    • 连接管理:可以控制连接数量,防止数据库过载
    • 超时处理:自动回收空闲连接,避免连接泄漏

    常见的数据库连接池实现:

    1. Hikari(黑卡里):Spring Boot 2.x 默认连接池,性能优异
    2. Druid(德鲁一):阿里巴巴开源,功能全面,监控完善
    3. Tomcat JDBC Pool:Tomcat 内置连接池
    4. C3P0:老牌连接池,稳定性好

    4.2 使用

    • Hikari:SpringBoot默认数据库连接池

    MyBatis XML开发全面完整指南

    • Druid:如果我们想把默认的数据库连接池切换为Druid数据库连接池,只需要引入相关依赖即可
    
     com.alibaba
     druid-spring-boot-3-starter
     1.2.21
    
    //如果SpringBoot版本为2.X, 使⽤druid-spring-boot-starter 依赖 
    
     com.alibaba
     druid-spring-boot-starter
     1.1.17
    

    五、小结

    这样,MyBatis XML开发的核心知识点就基本覆盖了。从配置文件到增删改查,再到动态SQL和安全注意事项,每一步都完整走通了。实际开发中,XML方式在复杂查询和团队协作方面优势明显,值得熟练掌握。

本文转载于:https://www.jb51.net/program/368689y3t.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。
  • using namespace 使用中遇到的问题怎么解决 正版软件
    using namespace 使用中遇到的问题怎么解决
    命名空间的基本概念与常见引入问题在C++等编程语言中,命名空间(namespace)是一种将代码标识符(如变量、函数、类名)封装在特定名称下的机制,其主要目的是避免命名冲突,尤其是在大型项目或使用多个第三方库时。使用“using namespace”指令可以将指定命名空间中的所有名称引入当前作用域,
    16小时前 07:27 0
  • c语言函数递归 实操经验总结:这些技巧很实用 正版软件
    c语言函数递归 实操经验总结:这些技巧很实用
    理解递归的基本原理在C语言中,递归是一种函数调用自身的编程技术。要掌握它,首先需要理解其核心思想:将一个复杂的大问题,分解为一个或几个与原问题相似但规模更小的子问题,直到子问题足够简单,可以直接求解。这个过程通常包含两个关键部分:递归出口和递归体。递归出口定义了问题何时不再继续分解,即最简单、可直接
    16小时前 07:26 0
  • c语言函数递归 怎么选?常见方案对比分析 正版软件
    c语言函数递归 怎么选?常见方案对比分析
    递归函数的基本概念与适用场景在C语言编程中,递归是一种函数调用自身的编程技巧。它并非适用于所有问题,但在处理某些具有自相似结构的问题时,能提供极其清晰和优雅的解决方案。递归的核心思想是将一个大规模问题分解为一个或多个同类型但规模更小的子问题,直到子问题简单到可以直接求解。典型的适用场景包括树形结构的
    16小时前 07:25 0
  • Objective-C 内存管理入门:从 alloc 到 dealloc 的生命周期详解 正版软件
    Objective-C 内存管理入门:从 alloc 到 dealloc 的生命周期详解
    理解内存管理的基石在Objective-C的编程世界中,内存管理是开发者必须掌握的核心技能之一。它直接关系到应用的性能、稳定性与资源利用效率。与一些采用自动垃圾回收机制的语言不同,Objective-C在很长一段时间里,依赖一套基于引用计数的、需要开发者部分介入的管理规则。这套规则的核心思想是明确的
    16小时前 07:23 0
  • 如何正确使用 dealloc 以避免 iOS 应用中的内存泄漏 正版软件
    如何正确使用 dealloc 以避免 iOS 应用中的内存泄漏
    理解 dealloc 的角色与时机在 iOS 应用开发中,内存管理是保障应用性能与稳定性的基石。dealloc 方法是 Objective-C 中对象生命周期结束时的关键回调,它标志着对象即将被系统回收内存。正确理解其触发时机至关重要:当一个对象的引用计数降为零时,运行时系统会自动调用该对象的 de
    16小时前 07:23 0

热门关注