您的位置:首页 >MyBatis XML开发全面完整指南
发布于2026-08-06 阅读(0)
扫一扫,手机访问
前期回顾:
MyBatis的开发有两种方式:
1.注解
2.XML
上一小节,我们聊了注解方式,这一节再来看XML方式。简单来说,注解适合快速搞定简单的增删改查,但一旦涉及复杂SQL逻辑,XML配置文件才是真正的利器——把SQL语句写在XML里,维护起来清晰得多。
用XML方式,主要完成两步:
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
持久层代码分两部分:

先加一个插件:

数据持久层的定义接口:
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();
}
//这里的namespace根据实际情况写
创建UserInfoXMLMapper.xml,路径参考properties/yml中的配置

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

将自动生成:

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);
}
}

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

—id:是和 Interface (接口)中定义的方法名称⼀样的,表示对接口的具体实现方法。
—resultType:是返回的数据类型,也就是开头我们定义的实体类。
在 MyBatis XML 中,插入操作使用
Mapper 接口方法定义:
// 插入用户信息 Integer insertUser(UserInfo userInfo);
XML 映射配置:
insert into user_info (username, password, age, gender, phone) values (#{username}, #{password}, #{age}, #{gender}, #{phone})
测试方法:
@Test
void insertUser() {
UserInfo user = new UserInfo();
user.setUsername("hhh1");
user.setPassword("123456");
user.setAge(20);
user.setGender(2);
user.setPhone("1235");
Integer row = userInfoXMLMapper.insertUser(user);
System.out.println("添加数据条数:" + row);
}
运行展示:

如果使用@Param设置参数名称,使用方法和注解类似:
//UserInfoXMLMapper接⼝:
Integer insertUser(@Param("userInfo") UserInfo userInfo);
//UserInfoXMLMapper.xml实现:
insert into user_info (username, password, age, gender, phone) values(#{userInfo.username},#{userInfo.password},#{userInfo.age},#{userInfo.gender},#{userInfo.phone})
返回自增id:接口定义不变,Mapper.xml实现 设置useGeneratedKeys和keyProperty属性
insert into user_info (username, password, age, gender, phone) values (#{username}, #{password}, #{age}, #{gender}, #{phone})
删除操作使用
Mapper 接口方法定义:
// 根据用户ID删除用户 Integer deleteUser(Integer id);
XML 映射配置:
delete from user_info where id = #{id}
测试方法:
@Test
void deleteUserByID() {
Integer rows =userInfoXMLMapper.deleteUserByID(6);
System.out.println("删除影响行数:" + rows);
}
运行展示:

更新操作使用
Mapper 接口方法定义:
// 根据用户ID更新用户信息 Integer updateUser(UserInfo userInfo);
XML 映射配置:
update user_info set username = #{username} where id = #{id}
测试方法:
@Test
void updateUser() {
UserInfo user = new UserInfo();
user.setId(1);
user.setUsername("h1");
Integer rows = userInfoXMLMapper.updateUser(user);
System.out.println("修改行数:" + rows);
}
运行展示:

查询操作使用
Mapper 接口方法定义(带参数查询):
// 根据用户名查询用户 UserInfo selectUserByName(String username);
XML 映射配置:
运行展示:

解决方法和类注解类似:
1.起别名
2.结果映射
3.开启驼峰命名
其中1,3的解决方法和注解一样,感兴趣的可以看上一篇文章,接下来介绍xml中的结果映射
通过 XML 配置 SQL,使得 SQL 语句与 Ja va 代码分离,结构更清晰,尤其便于维护复杂的动态 SQL
多表查询和单表查询类似,只是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);}
#{} 的使用示例:
@Select("select username, password, age, gender, phone from user_info where id = #{id}")
UserInfo queryById(Integer id);

我们发现我们输入的参数并没有在后面拼接,id值使用 ?进行占位,这中sql我们称为“预编译sql”
${} 的使用示例:
@Select("select username, password, age, gender, phone from user_info where id = ${id}")
UserInfo queryById(Integer id);

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

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

可以看到,这次参数依然是直接拼接在sql语句中了,但是字符串作为参数,需要添加单引号,使用${ }不会拼接引号,导致程序报错
修改代码为:
@Select("select username, password, age, gender, phone from user_info where username = '${name}'")
UserInfo queryByname(String name);

从上面例子可以看出:
#{} 使用的是预编译SQL, 通过 ? 占位的⽅式, 提前对SQL进行编译, 然后把参数填充到SQL语句中. #{} 会根据参数类型, ⾃动拼接引号 '' . ${} 会直接进行字符替换, ⼀起对SQL进行编译. 如果参数为字符串, 需要加上引号 '' . 参数为数字类型时, 也可以加上, 查询结果不变, 但是可能会导致索引失效, 性能下降.
总结:在大多数情况下,应优先使用 #{} 以确保安全性;只有在需要动态指定表名、字段名或排序方式等特殊场景下,才考虑使用 ${},并确保参数来源可信。
在 MyBatis 中实现动态排序功能时,由于 #{} 会对参数进行预编译处理并添加引号,导致 SQL 语句语法错误,因此需要使用 ${} 来实现。
Mapper 接口方法定义:
// 根据指定字段排序查询用户列表 ListselectUsersOrderBy(@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);
}
安全注意事项:
${} 时,必须确保参数值来自可信来源,避免用户直接输入在 MyBatis 中进行模糊查询时,虽然可以使用 ${},但由于安全考虑,推荐使用 #{} 配合 MySQL 的 CONCAT() 函数来实现。
Mapper 接口方法定义:
// 根据用户名模糊查询 ListselectUsersLikeName(@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}, '%')(如上例)性能优化建议:
%,这会导致索引失效数据库连接池(Database Connection Pool)是一种用于管理数据库连接的技术,它在应用程序启动时创建一定数量的数据库连接,并将这些连接保存在一个"池"中。当应用程序需要访问数据库时,从连接池中获取一个空闲连接,使用完毕后归还给连接池,而不是直接关闭连接。
数据库连接池的主要优势:
- 提高性能:避免了频繁创建和销毁连接的开销
- 资源复用:连接可以被多个请求重复使用
- 连接管理:可以控制连接数量,防止数据库过载
- 超时处理:自动回收空闲连接,避免连接泄漏
常见的数据库连接池实现:

//如果SpringBoot版本为2.X, 使⽤druid-spring-boot-starter 依赖 com.alibaba druid-spring-boot-3-starter 1.2.21 com.alibaba druid-spring-boot-starter 1.1.17
这样,MyBatis XML开发的核心知识点就基本覆盖了。从配置文件到增删改查,再到动态SQL和安全注意事项,每一步都完整走通了。实际开发中,XML方式在复杂查询和团队协作方面优势明显,值得熟练掌握。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8