XML语言
在开始介绍Mybatis之前,先介绍一下XML语言,XML语言发明最初是用于数据的存储和传输,它是由一个一个的标签嵌套而成
xml
<?xml version="1.0" encoding="UTF-8" ?>
<outer>
<name>阿伟</name>
<desc>怎么又在玩电动啊</desc>
<inner type="1">
<age>10</age>
<sex>男</sex>
</inner>
</outer>
JDK为我们内置了一个叫做org.w3c
的XML解析库,我们来看看如何使用它来进行XML文件内容解析:
java
// 创建DocumentBuilderFactory对象
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 创建DocumentBuilder对象
try {
DocumentBuilder builder = factory.newDocumentBuilder();
Document d = builder.parse("file:mappers/test.xml");
// 每一个标签都作为一个节点
NodeList nodeList = d.getElementsByTagName("test"); // 可能有很多个名字为test的标签
Node rootNode = nodeList.item(0); // 获取首个
NodeList childNodes = rootNode.getChildNodes(); // 一个节点下可能会有很多个节点,比如根节点下就囊括了所有的节点
//节点可以是一个带有内容的标签(它内部就还有子节点),也可以是一段文本内容
for (int i = 0; i < childNodes.getLength(); i++) {
Node child = childNodes.item(i);
if(child.getNodeType() == Node.ELEMENT_NODE) //过滤换行符之类的内容,因为它们都被认为是一个文本节点
System.out.println(child.getNodeName() + ":" +child.getFirstChild().getNodeValue());
// 输出节点名称,也就是标签名称,以及标签内部的文本(内部的内容都是子节点,所以要获取内部的节点)
}
} catch (Exception e) {
e.printStackTrace();
}
依赖管理
如果使用Maven可以直接引入:
xml
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.16</version>
</dependency>
依赖变多之后,我们可以将其放到一个单独的文件夹,不然会很繁杂:

依赖导入完成后,我们就可以编写Mybatis的配置文件了(现在不是在Java代码中配置了,而是通过一个XML文件去配置
配置文件架构
创建mybatis-config.xml
作为全局配置入口
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 加载 Mapper 文件 -->
<mappers>
<!--映射文件方式1:一个一个的配置 -->
<mapper resource="mapper/UserMapper.xml"/>
<!--<mapper resource="com/demo14/mapper/UserMapper.xml"/>-->
<!-- <mapper class="mapper.UserMapper.xml"/> 根据实际路径调整 -->
<!--映射方式2,自动扫描包内的Mapper接口与配置文件-->
<!--<package name="com.demo14.mapper"/>-->
</mappers>
</configuration>
实体类与映射文件
UserMapper.xml
是 MyBatis 实现 数据访问层 的核心文件,通过将接口方法与 SQL 绑定,简化数据库操作
xml
<select
id="唯一标识(必须与Mapper接口中的方法名一致用于绑定SQL与方法)"
parameterType="传入参数类型(可省略),MyBatis通过方法参数自动推断"
resultType="返回结果类型,MyBatis将查询结果自动映射到该实体类">
</select>
- 创建与数据库表对应的Java实体类,属性名需与字段名严格对应:
java
@Data
package com.demo14.entity;
/**
* 用户实体类
*/
public class User {
private Integer userid;
private String userName;
private String userPwd;
private Integer userage;
...
}
/**
* 用户接口类
*/
@WebServlet
public interface UserMapper {
public User queryUserByName(String userName);
}
- 编写Mapper XML文件
TestMapper.xml
:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 命名空间需与 Mapper 接口全限定名一致 -->
<mapper namespace="com.demo14.mapper.UserMapper">
<!--
id: 对应 Mapper 接口方法名
parameterType: 参数类型(可省略)
resultType: 返回结果实体类全限定名
-->
<!-- MyBatis 代理 -->
<select id="queryUserByName" parameterType="string" resultType="com.demo14.entity.User">
<!--SQL 执行-->
SELECT * FROM tb_user WHERE userName = #{userName}
</select>
</mapper>
_`resultType`指定结果映射的实体类全路径_
属性外部化
- 创建
jdbc.properties
文件管理数据库参数
properties
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/web_study
jdbc.username=test
jdbc.password=123456
- 配置文件引用:
xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--
properties 标签中的配置可以供整个配置文件使用,在任何位置都可以引入其中配置的值
properties 标签可以通过标签property标签来配置一些子元素信息,也可以配置外部的动态文件
-->
<!-- 加载外部属性文件(如 jdbc.properties)(支持多环境配置)-->
<properties resource="jdbc.properties"/>
<!-- 全局参数优化(生产环境必调参数) -->
<settings> <!-- 启用下划线转驼峰 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 启用日志输出 -->
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<!-- 全局设置 -->
<!--
<settings> 启用字段下划线转驼峰
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
-->
<!-- 配置类型别名(可选) -->
<!--
<typeAliases> 实体类包路径
<package name="com.example.entity"/>
</typeAliases>
-->
<!-- 数据库环境配置(需与 jdbc.properties 中的参数匹配) -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 加载 Mapper 文件 -->
<mappers>
<!--映射文件方式1:一个一个的配置 -->
<mapper resource="mapper/UserMapper.xml"/>
<!--<mapper resource="com/demo14/mapper/UserMapper.xml"/>-->
<!-- <mapper class="mapper.UserMapper.xml"/> 根据实际路径调整 -->
<!--映射方式2,自动扫描包内的Mapper接口与配置文件-->
<!--<package name="com.demo14.mapper"/>-->
</mappers>
</configuration>
为什么需要 MyBatis 的 <select>
标签配置?
1. 解耦 SQL 与 Java 代码
-
传统 JDBC 问题
SQL 与 Java 代码混杂,导致代码臃肿且难以维护。例如:java// 传统 JDBC 代码(硬编码 SQL) String sql = "SELECT * FROM user WHERE name = ?"; PreparedStatement stmt = connection.prepareStatement(sql); stmt.setString(1, "admin"); ResultSet rs = stmt.executeQuery();
- 缺点:SQL 修改需重新编译 Java 代码,且字符串拼接易引发 SQL 注入。
-
MyBatis 解决方案
将 SQL 独立到 XML 文件中,实现 业务逻辑与数据访问逻辑分离 :xml<!-- UserMapper.xml --> <select id="getUserByName" resultType="User"> SELECT * FROM user WHERE name = #{name} </select>
2. 自动结果集映射
-
传统 JDBC 问题
手动解析ResultSet
到 Java 对象,代码重复且易错:javaUser user = new User(); while (rs.next()) { user.setId(rs.getInt("id")); user.setName(rs.getString("name")); // ...其他字段 }
-
MyBatis 解决方案
通过resultType
或resultMap
自动映射查询结果到对象:xml<select id="getUserByName" resultType="com.example.User"> SELECT id, name, email FROM user WHERE name = #{name} </select>
3. 动态 SQL 支持
-
传统 JDBC 问题
拼接动态 SQL 易出错且难以维护:
javaString sql = "SELECT * FROM user WHERE 1=1 "; if (name != null) { sql += "AND name = '" + name + "' "; // 存在 SQL 注入风险 }
-
MyBatis 解决方案
使用
<if>
,<where>
,<foreach>
等标签实现动态 SQL:xml<select id="searchUsers" resultType="User"> SELECT * FROM user <where> <if test="name != null">AND name = #{name}</if> <if test="age != null">AND age = #{age}</if> </where> </select>
-
核心机制
MyBatis 通过 接口绑定 将 Mapper 接口与 XML SQL 关联:
java
public interface UserMapper {
public User queryUserByName(String userName);
}
- **工作流程**:
1. 调用 `userMapper.queryUserByName("admin")`。
2. MyBatis 动态代理接口,根据方法名 `getUserByName` 找到对应的 XML SQL。
3. 执行 SQL 并返回结果。
替代方案:简单项目可用注解,但 XML 仍是 MyBatis 的推荐实践
为何需要分别两个 mapper
目录?
这样做的原因是为了遵循Maven或Gradle的项目结构约定,构建工具会自动处理资源文件的打包和路径问题
职责分离
构建与部署规范
- Java 代码目录 (
src/main/java
)- 存放可编译的 Java 源文件(如
UserMapper.java
)。 - 构建工具(如 Maven/Gradle)会将其编译为
.class
文件。
- 存放可编译的 Java 源文件(如
- 资源目录 (
src/main/resources
)- 存放非代码文件(如 XML、配置文件)。
- 构建时,资源文件会被复制到
target/classes
(类路径),供 MyBatis 运行时加载。
流程:
-
开发者编写
UserMapper.java
接口。 -
在
UserMapper.xml
中编写对应的 SQL。 -
构建工具将 Java 代码编译为
.class
文件,资源文件复制到类路径 -
MyBatis 启动时,通过 接口名 + 方法名 动态绑定 XML 中的 SQL。
若合并目录:
- 将 XML 文件放在 Java 包目录中,可能导致构建工具忽略资源文件,引发 SQL 映射加载失败
MyBatis 的约定与配置
-
默认映射规则
MyBatis 要求 XML 文件的路径与接口包名一致。例如:
- 接口路径:
com.demo14.mapper.UserMapper
- XML 路径:
resources/mapper/UserMapper.xml
- 接口路径:
-
配置验证
在
mybatis-config.xml
或 Spring Boot 配置中需指定 XML 文件位置:xml<!-- MyBatis 配置 --> <mappers> <mapper resource="mapper/UserMapper.xml"/> </mappers>
-
在 Mapper 接口中定义方法,方法名就是SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致