MyBatis 从入门到精通(第二篇)—— 核心架构、配置解析与 Mapper 代理开发

        在第一篇博客中,我们掌握了 MyBatis 的基础概念与环境搭建,成功通过简单查询实现了数据持久化。但要真正用好 MyBatis,还需深入理解其 “内部工作原理” 与 “企业级开发规范”。本篇将聚焦三大核心:MyBatis 架构与核心类全局配置文件详解Mapper 代理开发(企业主流方案),帮你从 “会用” 升级到 “懂原理、能规范开发”。

目录

一、深入 MyBatis 架构:三层架构 + 核心类解析

1.1 三层架构:从 “调用入口” 到 “基础支撑”

(1)API 接口层:上层应用的 “交互入口”

(2)数据处理层(核心层):MyBatis 的 “业务大脑”

(3)基础支撑层:MyBatis 的 “后勤保障”

1.2 5 个核心类:MyBatis 的 “关键零件”

核心类工作流程示例(以 “查询部门” 为例):

二、MyBatis 全局配置文件:SqlMapConfig.xml 详解

2.1 properties标签:灵活管理数据源参数

方式 1:内部直接定义属性(简单但不推荐)

方式 2:加载外部jdbc.properties文件(推荐)

方式 3:动态传入属性(了解,特殊场景用)

2.2 settings标签:MyBatis 的 “运行开关”

配置示例:

2.3 typeAliases标签:简化全限定类名的 “别名神器”

方式 1:为单个类定义别名(简单场景用)

方式 2:为包下所有类定义别名(推荐,企业常用)

2.4 environments标签:多环境配置(开发 / 测试 / 生产)

配置示例:

关键子标签说明:

切换环境:

2.5 mappers标签:告诉 MyBatis “SQL 在哪里”

方式 1:加载类路径下的 Mapper.xml(入门用)

方式 2:加载本地文件系统的 Mapper.xml(了解)

方式 3:加载单个 Mapper 接口(Mapper 代理用)

方式 4:扫描包下所有 Mapper 接口(推荐,企业常用)

三、Mapper 代理开发:企业级 Dao 层开发规范

3.1 为什么要放弃 “原始 Dao 开发”?

3.2 Mapper 代理开发的 4 个核心规范

3.3 Mapper 代理开发实战步骤

步骤 1:创建 Mapper 接口(DeptMapper.java)

步骤 2:创建对应的 Mapper.xml(DeptMapper.xml)

步骤 3:配置SqlMapConfig.xml的mappers标签

步骤 4:编写测试类,通过代理对象调用方法

代理开发的优势总结:

四、总结与下一步预告


一、深入 MyBatis 架构:三层架构 + 核心类解析

        就像开车需要了解方向盘、油门的作用,使用 MyBatis 前,搞懂其架构与核心类,能让你在遇到问题时快速定位原因。MyBatis 的功能架构自上而下分为三层,核心类则是每层的 “关键执行器”。

1.1 三层架构:从 “调用入口” 到 “基础支撑”

MyBatis 的架构设计清晰,每层职责明确,协同完成数据库操作,具体如下:

(1)API 接口层:上层应用的 “交互入口”

        这是我们最常接触的一层,核心对象是SqlSession—— 它是上层应用(如 Service 层)与 MyBatis 的 “桥梁”,提供了 CRUD 操作的所有方法(如selectList()查询列表、insert()插入数据、update()更新数据)。
我们无需关心底层如何执行 SQL,只需通过SqlSession调用对应的方法即可。例如:

// 通过SqlSession调用查询方法,定位SQL的“namespace+id”
List<Dept> depts = session.selectList("com.jr.mapper.DeptMapper.selectDept");

SqlSession接收到调用请求后,会将任务交给下一层(数据处理层)执行。

(2)数据处理层(核心层):MyBatis 的 “业务大脑”

这是 MyBatis 的核心,负责完成数据库操作的全流程,主要做四件事:

  1. 参数映射:将 Java 代码传入的参数(如Integer deptno)解析并转换为 JDBC 支持的类型(如SQL INTEGER);
  2. SQL 解析:读取 Mapper.xml 中的 SQL 语句,处理动态 SQL(如<if><where>标签),生成最终可执行的 SQL;
  3. SQL 执行:通过执行器(Executor)调用 JDBC API 执行 SQL,与数据库交互;
  4. 结果映射:将数据库返回的 ResultSet 结果集,自动映射为 Java 实体类(如Dept对象),无需手动遍历赋值。

这一层的核心组件是Executor(执行器),它是 SQL 执行的 “实际操作者”,MyBatis 提供了三种常用执行器:

  • SimpleExecutor:默认执行器,每次执行 SQL 都会创建新的PreparedStatement
  • ReuseExecutor:重用PreparedStatement,避免重复创建,提升性能;
  • BatchExecutor:支持批量更新,适用于大量插入 / 更新场景。
(3)基础支撑层:MyBatis 的 “后勤保障”

这一层提供通用功能支撑,为上层(数据处理层)服务,核心能力包括:

  • 连接管理:通过数据源(DataSource)管理数据库连接,支持连接池(如POOLED类型),避免频繁创建 / 关闭连接;
  • 事务管理:支持 JDBC 事务(手动提交 / 回滚)和 MANAGED 事务(交给容器管理,如 Spring);
  • 缓存处理:实现一级缓存(SqlSession级别)和二级缓存(Mapper级别),减少数据库访问次数;
  • 工具类:提供 XML 解析、反射、日志打印等基础工具,简化框架内部逻辑。

1.2 5 个核心类:MyBatis 的 “关键零件”

理解核心类的作用与生命周期,是排查问题、优化性能的关键,下表整理了必须掌握的 5 个核心类:

核心类核心作用生命周期关键特点
SqlSessionFactory创建SqlSession的 “工厂”应用启动时创建,全局唯一一旦创建,需一直存在,不可重复创建(浪费资源)
SqlSession与数据库的 “一次会话”,提供 CRUD 方法每次操作数据库时创建,用完关闭非线程安全,必须手动关闭(推荐try-finally
Executor执行器,负责 SQL 的实际执行(查询 / 更新)每个SqlSession对应一个Executor可通过配置切换执行器类型(如批量执行器)
MappedStatement存储 Mapper.xml 中的 SQL 信息(id、参数、结果映射)应用启动时加载,全局唯一每个 SQL 节点(如<select>)对应一个实例
Configuration存储 MyBatis 的所有配置信息(数据源、映射、settings)应用启动时解析配置文件生成是 MyBatis 的 “配置中心”,所有核心类都依赖它
核心类工作流程示例(以 “查询部门” 为例):
  1. 应用启动时,解析SqlMapConfig.xmlDeptMapper.xml,生成Configuration对象;
  2. 通过SqlSessionFactoryBuilder读取Configuration,创建SqlSessionFactory
  3. 调用SqlSessionFactory.openSession(),创建SqlSession,并为其分配Executor
  4. 调用SqlSession.selectList("com.jr.mapper.DeptMapper.selectDept")SqlSession通过 “namespace+id” 找到对应的MappedStatement
  5. Executor根据MappedStatement中的 SQL 信息,执行 SQL 并处理结果,最终返回Dept列表;
  6. 关闭SqlSession,释放Executor与数据库连接。

二、MyBatis 全局配置文件:SqlMapConfig.xml 详解

SqlMapConfig.xml是 MyBatis 的 “全局控制中心”,所有影响 MyBatis 行为的配置都集中在这里。上篇我们只写了基础配置,本篇将详细解析 5 个核心配置标签,覆盖企业开发中的常用场景。

2.1 properties标签:灵活管理数据源参数

properties标签用于加载数据库连接参数(如驱动、URL、用户名、密码),避免硬编码在配置文件中,支持三种使用方式,推荐第二种(加载外部属性文件)

方式 1:内部直接定义属性(简单但不推荐)

直接在properties标签内写死参数,修改时需改配置文件,灵活性差:

<configuration><!-- 内部定义数据源参数 --><properties><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mytestdb?serverTimezone=GMT&amp;useSSL=false"/><property name="username" value="root"/><property name="password" value="root"/></properties><!-- 使用参数:${属性名} --><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments>
</configuration>
方式 2:加载外部jdbc.properties文件(推荐)

将参数放在独立的属性文件中,实现 “参数与配置分离”,修改参数无需动SqlMapConfig.xml

src/main/resources下新建jdbc.properties文件:

# jdbc.properties:单独存储数据源参数
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mytestdb?serverTimezone=GMT&useSSL=false
username=root
password=root

SqlMapConfig.xml中加载该文件:

<configuration><!-- 加载外部属性文件,resource指定文件路径(类路径下) --><properties resource="jdbc.properties"/><!-- 直接使用${属性名}引用参数 --><environments default="development"><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="${driver}"/><property name="url" value="${url}"/><property name="username" value="${username}"/><property name="password" value="${password}"/></dataSource></environment></environments>
</configuration>
方式 3:动态传入属性(了解,特殊场景用)

通过SqlSessionFactoryBuilder.build()方法动态传入参数,覆盖配置文件中的值,适用于 “临时切换数据源” 场景:

// 1. 加载配置文件
InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
// 2. 动态创建属性,覆盖url
Properties props = new Properties();
props.setProperty("url", "jdbc:mysql://localhost:3306/testdb2?serverTimezone=GMT&useSSL=false");
// 3. 传入属性,创建SqlSessionFactory
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is, props);

重要优先级规则:动态传入的属性 > 外部属性文件 > 内部定义的属性,即后加载的属性会覆盖先加载的同名属性。

2.2 settings标签:MyBatis 的 “运行开关”

settings标签用于配置 MyBatis 的全局运行参数,这些参数直接影响框架的性能与行为。企业开发中常用的配置如下:

设置项作用描述默认值推荐配置
cacheEnabled开启全局二级缓存(后续博客详解)true保持默认 true
lazyLoadingEnabled开启延迟加载(按需加载关联数据,如查员工时不默认查部门)false复杂项目设为 true
aggressiveLazyLoading开启 “积极懒加载”:访问实体类任一属性,加载所有关联数据false(3.4.1+)设为 false(按需加载,更灵活)
mapUnderscoreToCamelCase开启 “下划线转驼峰”:数据库字段dept_name自动映射为实体类属性deptNamefalse必须设为 true(避免手动映射字段)
logImpl指定日志实现(如 SLF4J、LOG4J)未设置开发环境设为 LOG4J(方便看 SQL 日志)
配置示例:
<configuration><properties resource="jdbc.properties"/><!-- settings标签必须在properties之后、typeAliases之前 --><settings><!-- 开启下划线转驼峰,避免手动映射字段 --><setting name="mapUnderscoreToCamelCase" value="true"/><!-- 开启延迟加载,优化关联查询性能 --><setting name="lazyLoadingEnabled" value="true"/><!-- 关闭积极懒加载,按需加载关联数据 --><setting name="aggressiveLazyLoading" value="false"/></settings><!-- 其他配置... -->
</configuration>

2.3 typeAliases标签:简化全限定类名的 “别名神器”

        在 Mapper.xml 中,resultType/parameterType需要写实体类的全限定类名(如com.jr.pojo.Dept),重复书写繁琐且易出错。typeAliases标签可给实体类定义 “别名”,简化书写。

方式 1:为单个类定义别名(简单场景用)
<configuration><properties resource="jdbc.properties"/><settings>...</settings><!-- 为单个实体类定义别名 --><typeAliases><!-- alias:别名,type:实体类全限定类名 --><typeAlias alias="dept" type="com.jr.pojo.Dept"/><typeAlias alias="emp" type="com.jr.pojo.Emp"/></typeAliases><!-- 其他配置... -->
</configuration>

使用时直接写别名,无需全限定类名:

<!-- Mapper.xml中使用别名 -->
<select id="selectDept" resultType="dept"> <!-- 直接用“dept”代替“com.jr.pojo.Dept” -->select * from dept
</select>
方式 2:为包下所有类定义别名(推荐,企业常用)

        若实体类较多,逐个定义别名太麻烦,可直接扫描整个包,MyBatis 会自动将 “类名首字母小写” 作为别名(如DeptdeptEmpemp):

<configuration><properties resource="jdbc.properties"/><settings>...</settings><!-- 扫描com.jr.pojo包下所有实体类,自动生成别名 --><typeAliases><package name="com.jr.pojo"/></typeAliases><!-- 其他配置... -->
</configuration>

特殊需求:若想自定义别名(不使用首字母小写),可在实体类上添加@Alias注解:

import org.apache.ibatis.type.Alias;@Alias("myDept") // 自定义别名“myDept”
public class Dept {// 实体类属性、getter/setter...
}

使用时直接写自定义别名:

<select id="selectDept" resultType="myDept">select * from dept
</select>

2.4 environments标签:多环境配置(开发 / 测试 / 生产)

        实际项目中,开发、测试、生产环境的数据库配置不同(如开发用本地库,生产用服务器库),environments标签支持配置多个环境,默认激活一个。

配置示例:
<configuration><properties resource="jdbc.properties"/><settings>...</settings><typeAliases>...</typeAliases><!-- default:默认激活的环境ID(此处为开发环境) --><environments default="development"><!-- 开发环境 --><environment id="development"><!-- 事务管理器:JDBC(手动控制事务) --><transactionManager type="JDBC"/><!-- 数据源:POOLED(连接池,开发/测试用) --><dataSource type="POOLED"><property name="driver" value="${dev.driver}"/><property name="url" value="${dev.url}"/><property name="username" value="${dev.username}"/><property name="password" value="${dev.password}"/></dataSource></environment><!-- 生产环境 --><environment id="production"><!-- 事务管理器:MANAGED(交给Spring容器管理) --><transactionManager type="MANAGED"/><!-- 数据源:POOLED(生产环境也用连接池,提升性能) --><dataSource type="POOLED"><property name="driver" value="${prod.driver}"/><property name="url" value="${prod.url}"/><property name="username" value="${prod.username}"/><property name="password" value="${prod.password}"/></dataSource></environment></environments><!-- 其他配置... -->
</configuration>

对应的jdbc.properties需包含多环境参数:

# 开发环境参数
dev.driver=com.mysql.cj.jdbc.Driver
dev.url=jdbc:mysql://localhost:3306/dev_db?serverTimezone=GMT&useSSL=false
dev.username=root
dev.password=root# 生产环境参数
prod.driver=com.mysql.cj.jdbc.Driver
prod.url=jdbc:mysql://192.168.1.100:3306/prod_db?serverTimezone=GMT&useSSL=false
prod.username=prod_user
prod.password=prod_pwd
关键子标签说明:
  • transactionManager(事务管理器)
    支持两种类型:JDBC(依赖数据源连接,手动调用session.commit()提交事务)和MANAGED(不管理事务,交给容器如 Spring 处理,MyBatis 只负责 SQL 执行)。
  • dataSource(数据源)
    支持三种类型:
    • POOLED:连接池,创建连接池管理连接,避免频繁创建 / 关闭,开发 / 测试 / 生产都推荐;
    • UNPOOLED:无连接池,每次执行 SQL 都新建连接,性能差,仅适用于小规模项目;
    • JNDI:从应用服务器(如 Tomcat)的 JNDI 数据源获取连接,适用于 JavaEE 企业级项目。
切换环境:

默认使用default指定的环境,若需切换(如测试时用生产环境配置),可在创建SqlSessionFactory时指定环境 ID:

InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
// 指定激活“production”环境
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is, "production");

2.5 mappers标签:告诉 MyBatis “SQL 在哪里”

mappers标签用于配置 “Mapper 映射文件” 或 “Mapper 接口” 的位置 ——MyBatis 需要通过它找到我们写的 SQL 语句,常用四种配置方式,企业开发推荐后两种(Mapper 代理用)

方式 1:加载类路径下的 Mapper.xml(入门用)

通过resource指定 Mapper.xml 的类路径,适用于 “普通项目” 或 “非代理开发” 场景:

<mappers><mapper resource="com/jr/mapper/DeptMapper.xml"/><mapper resource="com/jr/mapper/EmpMapper.xml"/>
</mappers>
方式 2:加载本地文件系统的 Mapper.xml(了解)

通过url指定本地文件的绝对路径,适用于 Mapper.xml 不在类路径下的场景(很少用):

<mappers><mapper url="file:///D:/mybatis-project/mappers/DeptMapper.xml"/>
</mappers>
方式 3:加载单个 Mapper 接口(Mapper 代理用)

通过class指定 Mapper 接口的全限定类名,适用于 “Mapper 代理开发”(后续详解),要求:Mapper 接口与 Mapper.xml 在同一包下,且文件名相同

<mappers><mapper class="com.jr.mapper.DeptMapper"/><mapper class="com.jr.mapper.EmpMapper"/>
</mappers>
方式 4:扫描包下所有 Mapper 接口(推荐,企业常用)

通过package扫描整个包下的所有 Mapper 接口,自动关联对应的 Mapper.xml,要求与方式 3 一致(接口与 XML 同包同名),简化大量配置:

<mappers><!-- 扫描com.jr.mapper包下所有Mapper接口 --><package name="com.jr.mapper"/>
</mappers>

三、Mapper 代理开发:企业级 Dao 层开发规范

        在第一篇的环境搭建中,我们通过SqlSession.selectList("namespace+id")调用 SQL,这种方式属于 “原始 Dao 开发”。但在企业项目中,更推荐Mapper 代理开发—— 无需编写 Dao 接口的实现类,MyBatis 会自动生成代理对象,大幅减少重复代码。

3.1 为什么要放弃 “原始 Dao 开发”?

原始 Dao 开发需要手动编写 Dao 接口的实现类(如DeptDaoImpl),存在三个明显缺点:

  1. 模板代码冗余:实现类中大量重复代码(如创建SqlSession、调用方法、关闭SqlSession),开发者沦为 “代码搬运工”;
  2. SQL ID 硬编码:调用SqlSession方法时,需写死 SQL 的 “namespace+id”(如session.selectList("com.jr.mapper.DeptMapper.selectDept")),写错不会在编译期报错,只能在运行时发现;
  3. 类型不安全SqlSession的方法参数与返回值大量使用泛型(如selectList()返回List<Object>),若参数类型或返回值类型错误,编译期无法察觉。

而 Mapper 代理开发能完美解决这些问题 —— 只需写 “Mapper 接口” 和 “Mapper.xml”,MyBatis 自动生成实现类代理对象,既简洁又安全。

3.2 Mapper 代理开发的 4 个核心规范

要让 MyBatis 自动生成代理对象,必须遵守以下 4 个规范(缺一不可),否则框架无法关联接口与 SQL:

  1. 接口与 XML 同包同名:Mapper 接口(如DeptMapper.java)与 Mapper.xml(如DeptMapper.xml)必须在同一包下,且文件名完全相同;
  2. XML 的 namespace 与接口全路径一致:Mapper.xml 的namespace属性必须等于 Mapper 接口的全限定类名(如com.jr.mapper.DeptMapper);
  3. 接口方法名与 XML 的 SQL ID 一致:Mapper 接口中的方法名(如selectDept())必须等于 Mapper.xml 中 SQL 标签的id(如<select id="selectDept">);
  4. 接口方法参数 / 返回值与 XML 匹配
    • 接口方法的参数类型 ≡ XML 中 SQL 的parameterType
    • 接口方法的返回值类型 ≡ XML 中 SQL 的resultType/resultMap(若返回列表,返回值类型为List<实体类>,XML 中resultType为单个实体类)。

3.3 Mapper 代理开发实战步骤

以 “查询部门列表” 为例,完整演示 Mapper 代理开发的流程(基于 Maven 项目):

步骤 1:创建 Mapper 接口(DeptMapper.java)

src/main/java/com/jr/mapper下创建接口,定义查询方法,无需写实现类:

package com.jr.mapper;import com.jr.pojo.Dept;
import java.util.List;// 规范1:接口名与后续XML文件名相同(DeptMapper)
public interface DeptMapper {// 规范3:方法名与XML中SQL的id一致(selectDept)// 规范4:返回值类型为List<Dept>,对应XML中resultType="dept"(单个实体类)List<Dept> selectDept();// 新增:根据部门编号查询单个部门(演示参数匹配)// 规范4:参数类型为int,对应XML中parameterType="int";返回值为Dept,对应resultType="dept"Dept selectDeptByNo(int deptno);
}
步骤 2:创建对应的 Mapper.xml(DeptMapper.xml)

src/main/resources/com/jr/mapper下创建 XML 文件(与接口同包同名),配置 SQL 并遵守规范:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- 规范2:namespace等于Mapper接口全路径(com.jr.mapper.DeptMapper) -->
<mapper namespace="com.jr.mapper.DeptMapper"><!-- 规范3:id等于接口方法名(selectDept) --><!-- 规范4:resultType="dept"(单个实体类),对应接口返回值List<Dept> --><select id="selectDept" resultType="dept">select * from dept</select><!-- 规范3:id等于接口方法名(selectDeptByNo) --><!-- 规范4:parameterType="int"(接口方法参数类型),resultType="dept"(返回值类型) --><select id="selectDeptByNo" parameterType="int" resultType="dept">select * from dept where deptno = #{deptno}</select>
</mapper>
步骤 3:配置SqlMapConfig.xmlmappers标签

使用 “扫描包” 方式加载 Mapper 接口(企业推荐):

<configuration><properties resource="jdbc.properties"/><settings><setting name="mapUnderscoreToCamelCase" value="true"/></settings><typeAliases><package name="com.jr.pojo"/> <!-- 扫描实体类,生成别名 --></typeAliases><environments default="development"><!-- 数据源配置... --></environments><!-- 规范:扫描Mapper接口所在包,自动关联XML --><mappers><package name="com.jr.mapper"/></mappers>
</configuration>
步骤 4:编写测试类,通过代理对象调用方法

通过SqlSession.getMapper(接口.class)获取 MyBatis 自动生成的代理对象,直接调用接口方法:

import com.jr.mapper.DeptMapper;
import com.jr.pojo.Dept;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;public class DeptMapperTest {private SqlSessionFactory factory;// 测试前初始化SqlSessionFactory(只执行一次)@Beforepublic void setUp() throws Exception {InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");factory = new SqlSessionFactoryBuilder().build(is);}// 测试查询所有部门@Testpublic void testSelectDept() {SqlSession session = null;try {session = factory.openSession();// 获取Mapper代理对象(MyBatis自动生成,无需手动new实现类)DeptMapper deptMapper = session.getMapper(DeptMapper.class);// 直接调用接口方法,底层自动执行SQLList<Dept> depts = deptMapper.selectDept();for (Dept dept : depts) {System.out.println(dept);}} finally {// 确保关闭会话if (session != null) {session.close();}}}// 测试根据部门编号查询@Testpublic void testSelectDeptByNo() {SqlSession session = null;try {session = factory.openSession();DeptMapper deptMapper = session.getMapper(DeptMapper.class);// 传入参数,调用方法Dept dept = deptMapper.selectDeptByNo(10);System.out.println(dept); // 输出:Dept{deptno=10, dname='ACCOUNTING', loc='NEW YORK'}} finally {if (session != null) {session.close();}}}
}
代理开发的优势总结:
  1. 无模板代码:无需写 Dao 实现类,MyBatis 自动生成代理对象;
  2. SQL ID 无硬编码:通过接口方法名关联 SQL,编译期可检查错误;
  3. 类型安全:接口方法的参数与返回值类型明确,编译期可发现类型错误;
  4. 符合面向接口编程:符合企业级开发规范,便于团队协作与后期维护。

四、总结与下一步预告

本篇博客我们深入 MyBatis 的核心:

  1. 理解了 MyBatis 的三层架构与核心类,知道 SQL 是如何从 “调用” 到 “执行” 的;
  2. 掌握了全局配置文件SqlMapConfig.xml的 5 个核心标签,能应对企业级项目的配置需求;
  3. 学会了 Mapper 代理开发规范,摆脱了原始 Dao 开发的冗余与不安全,实现了 “接口 + XML” 的简洁开发。

第三篇预告:MyBatis 的 “高级特性”—— 动态 SQL(灵活处理多条件查询)、关联查询(一对一 / 一对多)、查询缓存(一级 / 二级缓存优化性能),这些是解决复杂业务场景的关键,也是面试高频考点。跟着系列博客一步步深入,你会发现 MyBatis 的强大与灵活,真正做到 “知其然,更知其所以然”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/923607.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/923607.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp+<script setup lang=“ts“>单个时间格式转换(format)

有问题的时间&#xff08;只示例&#xff0c;不是真实数据&#xff09;修改后的时间展示&#xff08;只示例&#xff0c;不是真实数据&#xff09;原代码<view v-else-if"item?.payTime" class"order-info-item">支付时间&#xff1a;item?.payTim…

运维安全05,iptables规则保存与恢复

一&#xff1a;网络安全1.1、昨日功能优化配置后引发的问题&#xff1a;配置iptables后防火墙起到了防护作用&#xff0c;但使用127.0.0.1访问不了数据库了[rootlocalhost /]# mysql -u admin -p -h 127.0.0.1 Enter password:思考&#xff1a;如果使用localhost可以访问吗&…

线性代数 · 矩阵 | 秩 / 行秩 / 列秩 / 计算方法

注&#xff1a;本文为 “线性代数 矩阵 | 秩” 相关合辑。 图片清晰度受引文原图所限。 略作重排&#xff0c;未全校去重。 如有内容异常&#xff0c;请看原文。 矩阵的秩及其应用 一、矩阵秩的基本概念 &#xff08;一&#xff09;k 阶子式 设矩阵 A(aij)mnA (a_{ij})_{m…

Ajax-day2(图书管理)-弹框显示和隐藏

Bootstrap 弹框图书管理-Bootsrap 弹框&#xff08;一&#xff09;属性控制一、模板代码二、弹框模板三、bootsrap 的显示弹框属性完整代码&#xff08;二&#xff09;JS 控制一、模板代码二、步骤图书管理-Bootsrap 弹框 Bootstrap 框架渲染列表&#xff08;查&#xff09;新…

【Linux网络】认识https

认识https一&#xff0c;概念铺垫1.1 什么是加密&#xff1f;1.2 为什么要加密&#xff1f;1.3 加密的方式1.4 数据摘要&数据指纹二&#xff0c;认识https2.1 方案1-只使用对称加密2.2 方案2-只使用非对称加密2.3 方案3-双方都使用非对称加密2.4 方案4-非对称加密对称加密2…

OC-AFNetworking

文章目录AFNetworking简介问题&#x1f914;优化策略解决AFNetworking局限性使用单例进行网络请求的优势使用单例进行网络请求的风险最优使用使用参数讲解POST请求AFNetworking 简介 这篇文章旨在实现使用AFNetworking设置一个集中的单通道网络对象&#xff0c;该对象与MVC组建…

【数据结构】跳表

目录 1.什么是跳表-skiplist 2.skiplist的效率如何保证&#xff1f; 3.skiplist的实现 3.1节点和成员设计 3.2查找实现 3.3前置节点查找 3.4插入实现 3.5删除实现 3.6随机层数 3.7完整代码 4.skiplist跟平衡搜索树和哈希表的对比 1.什么是跳表-skiplist skiplist是由…

html实现右上角有个图标,鼠标移动到该位置出现手型,点击会弹出登录窗口。

写了一段html代码实现的效果&#xff1a;实现右上角有个图标&#xff0c;鼠标移动到该位置出现手型&#xff0c;点击会弹出登录窗口。功能实现前端&#xff0c;没有实现后端。<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF…

STM32G4 电流环闭环(二) 霍尔有感运行

目录一、STM32G4 电流环闭环(二) 霍尔有感运行2. 霍尔有感运行附学习参考网址欢迎大家有问题评论交流 (* ^ ω ^)一、STM32G4 电流环闭环(二) 霍尔有感运行 2. 霍尔有感运行 文章使用的BLDC在定子侧以互差120电角度的位置安装三个霍尔元件Ha&#xff0c;Hb&#xff0c;Hc。当…

展示框选择

好的&#xff0c;非常感谢您提供更详细的项目情况。这是一个非常典型的父子组件通信场景。 根据您的新需求&#xff0c;我将对代码进行重构&#xff1a; FaultSelect.vue (子组件): 这个组件现在将变得更加“纯粹”。它只负责自身的下拉框逻辑&#xff0c;不关心外部按钮&#…

第5课:上下文管理与状态持久化

第5课:上下文管理与状态持久化 课程目标 掌握上下文存储和检索策略 学习会话状态管理 了解数据持久化方案 实践实现上下文管理系统 课程内容 5.1 上下文管理基础 什么是上下文管理? 上下文管理是Agent系统中维护和利用历史信息的能力,包括: 对话历史:用户与Agent的交互…

计算机毕业设计 基于大数据技术的医疗数据分析与研究 Python 大数据毕业设计 Hadoop毕业设计选题【附源码+文档报告+安装调试】

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python、大数据、人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&…

K8S集群管理(2)

目录 1.什么是Pod的根容器&#xff1f; 2.解释Pod的生命周期。 3.Init类型容器有什么特点&#xff0c;主要用途&#xff1f; 4.Sidecar类型容器和Init容器的区别在哪&#xff1f; 5.什么是静态Pod&#xff1f; 6.说明K8s控制器的作用&#xff1f; 7.什么是ReplicaSet&#xff0…

视频全模态referring分割:Ref-AVS: Refer and Segment Objects in Audio-Visual Scenes

一、TL&#xff1b;DR 为什么要做&#xff1a;传统的referring分割无法使用音频模态&#xff0c;本文提出Reference audio-visual Segmentation本文怎么做&#xff1a;构建首个 Ref-AVS 基准数据集通过充分利用多模态提示&#xff0c;将音频信息通过和文本融合作为载体&#x…

A股大盘数据-20250916分析

&#x1f4ca; 一、大盘数据深度分析1.1 &#x1f9ee; 市场活跃度与资金流向总成交额&#xff1a;沪深京合计约 2.37万亿元&#xff0c;市场交投活跃&#xff0c;深市成交&#xff08;13516.4亿&#xff09;明显高于沪市&#xff08;9897.9亿&#xff09;&#xff0c;显示中小…

[计算机毕业设计]基于深度学习的噪声过滤音频优化系统研究

前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科同学来说是充满挑战。为帮助大家顺利通过和节省时间与精力投…

贪心算法应用:NFV功能部署问题详解

Java中的贪心算法应用&#xff1a;NFV功能部署问题详解 1. NFV功能部署问题概述 网络功能虚拟化(NFV, Network Function Virtualization)是一种将传统网络设备功能从专用硬件转移到虚拟化软件的技术。在NFV功能部署问题中&#xff0c;我们需要将各种虚拟网络功能(VNFs)部署到有…

SeriLog测试

安装Serilog.Sinks.Seq(5.2.3.0)&#xff0c;Serilog.Sinks.File(7.0.0) 下载Seq安装包并安装&#xff08;https://datalust.co/download&#xff09; 代码如下&#xff1a; private Logger _logger;private void button1_Click(object sender, EventArgs e){_logger new Lo…

HarmonyOS 5.0应用开发——V2装饰器@param的使用

【高心星出品】 文章目录V2装饰器param的使用概念使用方法案例V2装饰器param的使用 概念 在鸿蒙ArkTS开发中&#xff0c;Param装饰器是组件间状态管理的重要工具&#xff0c;主要用于父子组件间的单向数据传递&#xff0c;这一点与V1中的prop类似。 Param装饰的变量支持本地…

SLAM | 无人机视觉/激光雷达集群SLAM技术进展综述

主要内容如下: 无人机集群SLAM技术概述:介绍无人机集群SLAM的基本概念、重要性及面临的挑战,使用表格对比不同传感器配置的特点。 多传感器融合与协同SLAM架构:分析集中式、分布式和混合式协同架构的特点,使用表格对比不同架构的优缺点。 视觉协同SLAM的技术进展:总结直接…