XML语言

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 对象,代码重复且易错:

    java 复制代码
    User user = new User();
    while (rs.next()) {
      user.setId(rs.getInt("id"));
      user.setName(rs.getString("name"));
      // ...其他字段
    }
  • MyBatis 解决方案
    通过 resultTyperesultMap 自动映射查询结果到对象:

    xml 复制代码
    <select id="getUserByName" resultType="com.example.User">
      SELECT id, name, email FROM user WHERE name = #{name}
    </select>

3. 动态 SQL 支持

  • 传统 JDBC 问题

    拼接动态 SQL 易出错且难以维护:

    java 复制代码
    String 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 文件。
  • 资源目录 (src/main/resources)
    • 存放非代码文件(如 XML、配置文件)。
    • 构建时,资源文件会被复制到 target/classes(类路径),供 MyBatis 运行时加载。

流程

  1. 开发者编写 UserMapper.java 接口。

  2. UserMapper.xml 中编写对应的 SQL。

  3. 构建工具将 Java 代码编译为 .class 文件,资源文件复制到类路径

  4. 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,并保持参数类型和返回值类型一致

相关推荐
caihuayuan51 小时前
升级element-ui步骤
java·大数据·spring boot·后端·课程设计
佩奇的技术笔记2 小时前
Java学习手册:单体架构到微服务演进
java·微服务·架构
zm2 小时前
服务器多客户端连接核心要点(1)
java·开发语言
FuckPatience2 小时前
关于C#项目中 服务层使用接口的问题
java·开发语言·c#
天上掉下来个程小白3 小时前
缓存套餐-01.Spring Cache介绍和常用注解
java·redis·spring·缓存·spring cache·苍穹外卖
揣晓丹3 小时前
JAVA实战开源项目:健身房管理系统 (Vue+SpringBoot) 附源码
java·vue.js·spring boot·后端·开源
编程轨迹_3 小时前
使用 Spring 和 Redis 创建处理敏感数据的服务
java·开发语言·restful
奔驰的小野码3 小时前
SpringAI实现AI应用-自定义顾问(Advisor)
java·人工智能·spring boot·spring
奔驰的小野码3 小时前
SpringAI实现AI应用-使用redis持久化聊天记忆
java·数据库·人工智能·redis·spring
裁二尺秋风4 小时前
k8s(11) — 探针和钩子
java·容器·kubernetes