<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss/feed.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>星海日和</title><description>于群星与潮汐之间，记录旅途与幻想</description><link>https://blog.hoshiumi.xyz</link><item><title>MySQL安装与使用</title><link>https://blog.hoshiumi.xyz/post/lab/mysqlan-zhuang-yu-shi-yong</link><guid isPermaLink="false">lab/mysqlan-zhuang-yu-shi-yong</guid><description>MySQL 8.4.11 Windows 安装与使用教程

适用于 Windows 10 / 11，包含 MySQL Server 8.4.11 LTS 安装、初始化配置、服务管理、Navicat Premium 17 连接以及 PowerShell 基础操作。

开始前
本教程使用以下环境：</description><pubDate>Mon, 31 Aug 2026 09:39:22 GMT</pubDate><content:encoded>&lt;h1&gt;MySQL 8.4.11 Windows 安装与使用教程&lt;a href=&quot;#mysql-8411-windows-安装与使用教程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;适用于 Windows 10 / 11，包含 MySQL Server 8.4.11 LTS 安装、初始化配置、服务管理、Navicat Premium 17 连接以及 PowerShell 基础操作。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;开始前&lt;a href=&quot;#开始前&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;本教程使用以下环境：&lt;/p&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;项目&lt;/th&gt;&lt;th&gt;本教程环境&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;操作系统&lt;/td&gt;&lt;td&gt;Windows 10 / Windows 11（64 位）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;数据库&lt;/td&gt;&lt;td&gt;MySQL Community Server 8.4.11 LTS&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;安装包&lt;/td&gt;&lt;td&gt;&lt;code&gt;mysql-8.4.11-winx64.msi&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;图形化管理工具&lt;/td&gt;&lt;td&gt;Navicat Premium 17&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MySQL 服务名&lt;/td&gt;&lt;td&gt;&lt;code&gt;MySQL84&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;默认连接端口&lt;/td&gt;&lt;td&gt;&lt;code&gt;3306&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;p&gt;如果已经拿到配套“资料”文件夹，其中包含 &lt;code&gt;Navicat17&lt;/code&gt; 文件夹和 &lt;code&gt;mysql-8.4.11-winx64.msi&lt;/code&gt;，可以直接开始安装，不必重复下载。&lt;/p&gt;
&lt;/div&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174333913.png&quot; alt=&quot;配套资料文件夹&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;配套资料文件夹&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;本教程只介绍安装、初始化、连接和基础使用，不包含 MySQL 卸载。示例中 root 密码使用 &lt;code&gt;123456&lt;/code&gt;，仅用于课堂演示；实际使用时应设置更安全的密码。&lt;/p&gt;
&lt;p&gt;Navicat Premium 为商业软件，请使用官方试用版、正版授权或学校 / 组织提供的合法授权。&lt;/p&gt;
&lt;h3&gt;下载地址&lt;a href=&quot;#下载地址&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.mysql.com/downloads/mysql/8.4.html&quot;&gt;MySQL Community Server 8.4 官方下载&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.csdn.net/ctyy22/article/details/161624948&quot;&gt;Navicat Premium 17 安装参考（CSDN）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pan.quark.cn/s/6626d8e33003&quot;&gt;配套安装资料（夸克网盘）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;安装 MySQL Server&lt;a href=&quot;#安装-mysql-server&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;下载 MSI 安装包&lt;a href=&quot;#下载-msi-安装包&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;打开 MySQL Community Server 官方下载页面：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Select Version&lt;/strong&gt;：选择 &lt;strong&gt;8.4.11 LTS&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Select Operating System&lt;/strong&gt;：选择 &lt;strong&gt;Microsoft Windows&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;下载类型：选择 &lt;strong&gt;Windows (x86, 64-bit), MSI Installer&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本教程使用的安装包为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;mysql-8.4.11-winx64.msi&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;大小约 130 MB。这里建议使用 MSI Installer，而不是 ZIP Archive，因为 MSI 可以直接通过图形化安装向导完成安装，并包含后续需要使用的 MySQL Configurator。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174357398.png&quot; alt=&quot;MySQL Community Server 下载页面&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;MySQL Community Server 下载页面&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;点击 &lt;strong&gt;Download&lt;/strong&gt; 后，Oracle 页面可能要求登录账号。安装 Community Server 不要求必须注册，可以点击：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;No thanks, just start my download.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;直接开始下载。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174401025.png&quot; alt=&quot;跳过 Oracle 账号登录&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;跳过 Oracle 账号登录&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174404827.png&quot; alt=&quot;MySQL MSI 安装包下载中&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;MySQL MSI 安装包下载中&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;运行安装程序&lt;a href=&quot;#运行安装程序&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;双击 &lt;code&gt;mysql-8.4.11-winx64.msi&lt;/code&gt;。如果 Windows 弹出“用户账户控制”提示，选择“是”。&lt;/p&gt;
&lt;p&gt;进入 &lt;strong&gt;MySQL Server 8.4 Setup Wizard&lt;/strong&gt; 后点击 &lt;strong&gt;Next&lt;/strong&gt;。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174406481.png&quot; alt=&quot;MySQL Server 安装向导&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;MySQL Server 安装向导&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;在 &lt;strong&gt;End-User License Agreement&lt;/strong&gt; 页面勾选：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;I accept the terms in the License Agreement&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;然后点击 &lt;strong&gt;Next&lt;/strong&gt;。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174409957.png&quot; alt=&quot;接受许可协议&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;接受许可协议&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;选择 Typical 安装&lt;a href=&quot;#选择-typical-安装&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 &lt;strong&gt;Choose Setup Type&lt;/strong&gt; 页面可以看到 &lt;strong&gt;Typical&lt;/strong&gt;、&lt;strong&gt;Custom&lt;/strong&gt; 和 &lt;strong&gt;Complete&lt;/strong&gt; 三种安装方式。&lt;/p&gt;
&lt;p&gt;用于课程学习和常规开发时，选择 &lt;strong&gt;Typical&lt;/strong&gt; 即可。该模式会安装常用的 MySQL Server 组件，后续可以直接通过 Navicat、Java、Python 等程序连接。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174412786.png&quot; alt=&quot;选择 Typical 安装&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;选择 Typical 安装&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;进入 &lt;strong&gt;Ready to install MySQL Server 8.4&lt;/strong&gt; 页面后点击 &lt;strong&gt;Install&lt;/strong&gt;。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174527618.png&quot; alt=&quot;准备安装 MySQL Server&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;准备安装 MySQL Server&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;安装完成后，保持 &lt;strong&gt;Run MySQL Configurator&lt;/strong&gt; 处于勾选状态，然后点击 &lt;strong&gt;Finish&lt;/strong&gt;。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174414343.png&quot; alt=&quot;安装完成并启动 MySQL Configurator&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;安装完成并启动 MySQL Configurator&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;接下来会自动进入 MySQL 的首次初始化配置。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;初始化 MySQL&lt;a href=&quot;#初始化-mysql&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;安装完成并不代表 MySQL 已经可以直接使用。第一次安装后，还需要在 &lt;strong&gt;MySQL Configurator&lt;/strong&gt; 中完成数据目录、端口、root 密码、Windows 服务和文件权限等配置。&lt;/p&gt;
&lt;h3&gt;进入 Configurator&lt;a href=&quot;#进入-configurator&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 &lt;strong&gt;Welcome to the MySQL Server Configurator&lt;/strong&gt; 页面点击 &lt;strong&gt;Next&lt;/strong&gt;。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174416264.png&quot; alt=&quot;MySQL Server Configurator 欢迎页&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;MySQL Server Configurator 欢迎页&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;数据目录&lt;a href=&quot;#数据目录&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Data Directory&lt;/strong&gt; 用于保存 MySQL 的数据库数据文件。默认目录通常为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;C:\ProgramData\MySQL\MySQL Server 8.4\&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;普通学习和开发环境保持默认即可，然后点击 &lt;strong&gt;Next&lt;/strong&gt;。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174417696.png&quot; alt=&quot;MySQL 数据目录&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;MySQL 数据目录&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;网络与端口&lt;a href=&quot;#网络与端口&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;进入 &lt;strong&gt;Type and Networking&lt;/strong&gt; 后，按以下方式配置：&lt;/p&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;配置项&lt;/th&gt;&lt;th&gt;建议值&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Config Type&lt;/td&gt;&lt;td&gt;&lt;code&gt;Development Computer&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;TCP/IP&lt;/td&gt;&lt;td&gt;开启&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Port&lt;/td&gt;&lt;td&gt;&lt;code&gt;3306&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;X Protocol Port&lt;/td&gt;&lt;td&gt;&lt;code&gt;33060&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Named Pipe&lt;/td&gt;&lt;td&gt;不开启&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Shared Memory&lt;/td&gt;&lt;td&gt;不开启&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174419417.png&quot; alt=&quot;MySQL 网络与端口设置&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;MySQL 网络与端口设置&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Open Windows Firewall ports for network access&lt;/strong&gt; 用于把 MySQL 端口加入 Windows 防火墙规则。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;只在本机使用 Navicat、Java 或 Python 连接：可以取消勾选。&lt;/li&gt;
&lt;li&gt;需要其他计算机通过网络访问本机 MySQL：根据实际网络环境和安全要求配置防火墙。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;p&gt;后面连接 MySQL 时主要会用到下面三个参数：&lt;/p&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;参数&lt;/th&gt;&lt;th&gt;值&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Host&lt;/td&gt;&lt;td&gt;&lt;code&gt;localhost&lt;/code&gt; 或 &lt;code&gt;127.0.0.1&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Port&lt;/td&gt;&lt;td&gt;&lt;code&gt;3306&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;User&lt;/td&gt;&lt;td&gt;&lt;code&gt;root&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;h3&gt;设置 root 密码&lt;a href=&quot;#设置-root-密码&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 &lt;strong&gt;Accounts and Roles&lt;/strong&gt; 页面设置 root 管理员账户密码。&lt;/p&gt;
&lt;p&gt;本教程示例填写：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;123456&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在 &lt;strong&gt;MySQL Root Password&lt;/strong&gt; 和 &lt;strong&gt;Repeat Password&lt;/strong&gt; 中输入相同密码即可。下方 &lt;strong&gt;Add User&lt;/strong&gt; 可以创建普通账户，本教程暂不额外创建用户。&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;&lt;code&gt;123456&lt;/code&gt; 仅用于演示。真实项目中不要使用这种弱密码。&lt;/p&gt;
&lt;/div&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174421715.png&quot; alt=&quot;设置 root 密码&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;设置 root 密码&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;配置 Windows 服务&lt;a href=&quot;#配置-windows-服务&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 Windows Service 页面保持以下设置：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;勾选 &lt;strong&gt;Configure MySQL Server as a Windows Service&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Windows Service Name&lt;/strong&gt;：&lt;code&gt;MySQL84&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;勾选 &lt;strong&gt;Start the MySQL Server at System Startup&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;服务运行账户选择 &lt;strong&gt;Standard System Account&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这样 MySQL 会作为 Windows 服务运行，并在系统启动时自动启动。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174423183.png&quot; alt=&quot;配置 MySQL84 Windows 服务&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;配置 MySQL84 Windows 服务&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;文件权限与示例数据库&lt;a href=&quot;#文件权限与示例数据库&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 &lt;strong&gt;Server File Permissions&lt;/strong&gt; 页面保持默认第一项，使 MySQL 数据目录只向服务账户和管理员组提供完整访问权限。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174424618.png&quot; alt=&quot;MySQL 数据目录文件权限&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;MySQL 数据目录文件权限&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;接下来会询问是否创建 &lt;strong&gt;Sakila&lt;/strong&gt; 和 &lt;strong&gt;World&lt;/strong&gt; 示例数据库。本教程后面会自己创建 &lt;code&gt;test_db&lt;/code&gt; 和 &lt;code&gt;student&lt;/code&gt; 表，因此这两项都不勾选，直接点击 &lt;strong&gt;Next&lt;/strong&gt;。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174425742.png&quot; alt=&quot;不安装示例数据库&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;不安装示例数据库&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;应用配置&lt;a href=&quot;#应用配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;进入 &lt;strong&gt;Apply Configuration&lt;/strong&gt; 页面后点击 &lt;strong&gt;Execute&lt;/strong&gt;。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174427117.png&quot; alt=&quot;开始应用 MySQL 配置&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;开始应用 MySQL 配置&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Configurator 会自动完成配置文件写入、Windows 服务配置、数据库初始化、文件权限设置、服务启动和安全配置等操作。&lt;/p&gt;
&lt;p&gt;执行结束后，确认各项左侧均出现绿色对勾，并看到：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The configuration for MySQL Server 8.4.11 was successful.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174428854.png&quot; alt=&quot;MySQL 配置执行成功&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;MySQL 配置执行成功&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;如果出现红色错误标记，先打开 &lt;strong&gt;Log&lt;/strong&gt; 页签查看具体报错信息。&lt;/p&gt;
&lt;p&gt;最后点击 &lt;strong&gt;Next&lt;/strong&gt;，进入 &lt;strong&gt;Configuration Complete&lt;/strong&gt; 页面，再点击 &lt;strong&gt;Finish&lt;/strong&gt;。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174430457.png&quot; alt=&quot;MySQL 初始化配置完成&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;MySQL 初始化配置完成&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;至此，MySQL Server 8.4.11 已完成安装和初始化。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;管理 MySQL84 服务&lt;a href=&quot;#管理-mysql84-服务&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;MySQL Server 在 Windows 中以服务形式运行，本教程的服务名称是 &lt;code&gt;MySQL84&lt;/code&gt;。Navicat、终端以及其他程序要连接数据库，首先必须保证该服务正在运行。&lt;/p&gt;
&lt;h3&gt;在 Windows 服务中查看状态&lt;a href=&quot;#在-windows-服务中查看状态&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;按 &lt;span&gt;Win&lt;/span&gt; + &lt;span&gt;R&lt;/span&gt;，输入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;services.msc&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;按 &lt;span&gt;Enter&lt;/span&gt; 打开“服务”管理器，在列表中找到 &lt;code&gt;MySQL84&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;正常情况下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;状态：&lt;strong&gt;正在运行&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;启动类型：&lt;strong&gt;自动&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174432176.png&quot; alt=&quot;Windows 服务中的 MySQL84&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;Windows 服务中的 MySQL84&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;如果状态为空，说明服务已经停止。右键 &lt;code&gt;MySQL84&lt;/code&gt; 后可以选择“启动”“停止”或“重新启动”。&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;Navicat 突然无法连接 MySQL 时，优先检查 &lt;code&gt;MySQL84&lt;/code&gt; 是否正在运行。&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;使用终端管理服务&lt;a href=&quot;#使用终端管理服务&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;也可以用管理员权限打开 CMD、PowerShell 或 Windows Terminal，然后执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;net start MySQL84&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;net stop MySQL84&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;需要重新启动时，可以依次执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;net stop MySQL84&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;net start MySQL84&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果出现“拒绝访问”或权限不足，请确认终端是否以管理员身份运行。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;使用 Navicat 连接 MySQL&lt;a href=&quot;#使用-navicat-连接-mysql&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;安装并打开 Navicat&lt;a href=&quot;#安装并打开-navicat&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;配套资料中已经提供 &lt;code&gt;Navicat17&lt;/code&gt; 文件夹。如果需要自行安装，可以使用前面给出的安装参考。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174434390.png&quot; alt=&quot;Navicat Premium 17 安装参考&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;Navicat Premium 17 安装参考&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div&gt;
&lt;p&gt;Navicat Premium 为商业软件，请使用官方试用、正版授权或学校 / 组织提供的合法许可。&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;安装完成后打开 Navicat Premium 17。左侧“我的连接”用于管理数据库连接，顶部工具栏可以进行查询、表、视图、函数、用户和备份等操作。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174436352.png&quot; alt=&quot;Navicat Premium 17 主界面&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;Navicat Premium 17 主界面&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;新建 MySQL 连接&lt;a href=&quot;#新建-mysql-连接&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;点击左上角“连接”，选择 &lt;strong&gt;MySQL&lt;/strong&gt;，然后点击“下一步”。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174437436.png&quot; alt=&quot;选择 MySQL 连接类型&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;选择 MySQL 连接类型&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;在“新建连接（MySQL）”窗口中填写：&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;参数&lt;/th&gt;&lt;th&gt;示例值&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;连接名称&lt;/td&gt;&lt;td&gt;&lt;code&gt;MySQL84&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;主机&lt;/td&gt;&lt;td&gt;&lt;code&gt;localhost&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;端口&lt;/td&gt;&lt;td&gt;&lt;code&gt;3306&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;用户名&lt;/td&gt;&lt;td&gt;&lt;code&gt;root&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;密码&lt;/td&gt;&lt;td&gt;安装时设置的 root 密码&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;本教程示例密码为 &lt;code&gt;123456&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;填写完成后先点击“测试连接”。连接成功后，再点击“确定”保存。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174440244.png&quot; alt=&quot;Navicat MySQL 连接参数&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;Navicat MySQL 连接参数&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;如果测试连接失败，依次检查：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MySQL84&lt;/code&gt; 服务是否正在运行&lt;/li&gt;
&lt;li&gt;端口是否为 &lt;code&gt;3306&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;用户名是否为 &lt;code&gt;root&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;root 密码是否正确&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;查看系统数据库&lt;a href=&quot;#查看系统数据库&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;保存连接后，在左侧双击 &lt;code&gt;MySQL84&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;连接成功后一般可以看到：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;information_schema&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mysql&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;performance_schema&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sys&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些属于 MySQL 自身的系统数据库，初学阶段不建议随意修改。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174442344.png&quot; alt=&quot;MySQL 系统数据库&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;MySQL 系统数据库&lt;/figcaption&gt;&lt;/figure&gt;
&lt;hr /&gt;
&lt;h2&gt;创建数据库并练习 SQL&lt;a href=&quot;#创建数据库并练习-sql&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;接下来通过 Navicat 创建一个 &lt;code&gt;test_db&lt;/code&gt; 数据库，再创建 &lt;code&gt;student&lt;/code&gt; 表并完成插入和查询。&lt;/p&gt;
&lt;h3&gt;创建 test_db&lt;a href=&quot;#创建-test_db&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在左侧 &lt;code&gt;MySQL84&lt;/code&gt; 连接上右键，选择“新建数据库”。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174443806.png&quot; alt=&quot;新建数据库&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;新建数据库&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;数据库名称填写：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;test_db&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;字符集选择：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;utf8mb4&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;utf8mb4&lt;/code&gt; 可以完整保存 Unicode 字符，适合中文、英文及其他字符。排序规则保持默认即可。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174445569.png&quot; alt=&quot;创建 test_db 数据库&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;创建 test_db 数据库&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;创建 student 表&lt;a href=&quot;#创建-student-表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;选中 &lt;code&gt;test_db&lt;/code&gt;，点击“新建查询”，执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; student&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    id &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt; PRIMARY KEY&lt;/span&gt;&lt;span&gt; AUTO_INCREMENT,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    name&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    age &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    score &lt;/span&gt;&lt;span&gt;DECIMAL&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这张表包含 &lt;code&gt;id&lt;/code&gt;、&lt;code&gt;name&lt;/code&gt;、&lt;code&gt;age&lt;/code&gt; 和 &lt;code&gt;score&lt;/code&gt; 四个字段，其中 &lt;code&gt;id&lt;/code&gt; 是自增主键。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174447392.png&quot; alt=&quot;编写 CREATE TABLE 语句&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;编写 CREATE TABLE 语句&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;点击“运行”。如果下方显示“成功 1、错误 0”或 &lt;code&gt;OK&lt;/code&gt;，说明表已经创建成功。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174449045.png&quot; alt=&quot;student 表创建成功&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;student 表创建成功&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;插入测试数据&lt;a href=&quot;#插入测试数据&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;继续执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;INSERT INTO&lt;/span&gt;&lt;span&gt; student (&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;, age, score)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;张三&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;88&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;李四&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;21&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;92&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果结果显示：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Affected rows: 2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;说明两条数据插入成功。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174450699.png&quot; alt=&quot;向 student 表插入数据&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;向 student 表插入数据&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;查询数据&lt;a href=&quot;#查询数据&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; student;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;结果区域会显示 &lt;code&gt;id&lt;/code&gt;、&lt;code&gt;name&lt;/code&gt;、&lt;code&gt;age&lt;/code&gt;、&lt;code&gt;score&lt;/code&gt; 等字段和对应记录。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174452949.png&quot; alt=&quot;查询 student 表&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;查询 student 表&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div&gt;
&lt;p&gt;截图中张三和李四出现了重复记录，是因为 &lt;code&gt;INSERT&lt;/code&gt; 语句被执行了两次，不影响本教程对查询操作的说明。&lt;/p&gt;
&lt;/div&gt;
&lt;hr /&gt;
&lt;h2&gt;使用 PowerShell 操作 MySQL&lt;a href=&quot;#使用-powershell-操作-mysql&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Navicat 属于图形化管理工具，MySQL 也可以直接通过命令行客户端操作。掌握基本终端操作后，在没有图形界面的环境中也可以管理数据库。&lt;/p&gt;
&lt;h3&gt;进入 MySQL bin 目录&lt;a href=&quot;#进入-mysql-bin-目录&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MySQL 8.4 默认安装目录通常为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;C:\Program Files\MySQL\MySQL Server 8.4\bin&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;打开 PowerShell 或 Windows Terminal，执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;cd &lt;/span&gt;&lt;span&gt;&quot;C:\Program Files\MySQL\MySQL Server 8.4\bin&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;登录 MySQL&lt;a href=&quot;#登录-mysql&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 PowerShell 中运行当前目录下的 MySQL 客户端：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;.\mysql &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;u root &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;按 &lt;span&gt;Enter&lt;/span&gt; 后出现 &lt;code&gt;Enter password:&lt;/code&gt;，输入安装时设置的 root 密码。&lt;/p&gt;
&lt;p&gt;输入密码时终端通常不会显示字符，这是正常现象。登录成功后会出现：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;mysql&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以先查看当前服务器中的数据库：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;SHOW DATABASES;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174455930.png&quot; alt=&quot;PowerShell 登录 MySQL&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;PowerShell 登录 MySQL&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;查看 test_db 和 student&lt;a href=&quot;#查看-test_db-和-student&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;继续执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;USE&lt;/span&gt;&lt;span&gt; test_db;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;SHOW TABLES;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;DESC&lt;/span&gt;&lt;span&gt; student;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; student;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这些命令分别表示：&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;命令&lt;/th&gt;&lt;th&gt;作用&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;USE test_db;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;切换到 &lt;code&gt;test_db&lt;/code&gt; 数据库&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SHOW TABLES;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;查看当前数据库中的表&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DESC student;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;查看 &lt;code&gt;student&lt;/code&gt; 表结构&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SELECT * FROM student;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;查询 &lt;code&gt;student&lt;/code&gt; 表全部数据&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831174457791.png&quot; alt=&quot;终端查看 student 表结构和数据&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;终端查看 student 表结构和数据&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Navicat 和命令行连接的是同一个 MySQL Server，因此在 Navicat 中创建的数据库、表和数据，也可以直接在命令行中查询。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;常见问题&lt;a href=&quot;#常见问题&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Navicat 无法连接 MySQL&lt;a href=&quot;#navicat-无法连接-mysql&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;先检查 &lt;code&gt;MySQL84&lt;/code&gt; 服务是否正在运行。&lt;/p&gt;
&lt;p&gt;按 &lt;span&gt;Win&lt;/span&gt; + &lt;span&gt;R&lt;/span&gt;，输入 &lt;code&gt;services.msc&lt;/code&gt;；或者用管理员终端执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;net start MySQL84&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果服务本身没有启动，Navicat 无法正常连接。&lt;/p&gt;
&lt;h3&gt;Access denied for user root&lt;a href=&quot;#access-denied-for-user-root&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;通常是用户名或密码不正确。&lt;/p&gt;
&lt;p&gt;检查以下内容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用户名是否为 &lt;code&gt;root&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;输入的密码是否与 Configurator 中设置的一致&lt;/li&gt;
&lt;li&gt;Navicat 是否保存了旧密码&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果 Navicat 保存的是旧密码，编辑连接后重新输入即可。&lt;/p&gt;
&lt;h3&gt;3306 端口连接失败&lt;a href=&quot;#3306-端口连接失败&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;确认 Navicat 使用的端口和 MySQL Configurator 中设置的端口一致，本教程为 &lt;code&gt;3306&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;如果本机已有其他程序占用 &lt;code&gt;3306&lt;/code&gt;，MySQL 服务可能无法正常启动，需要检查端口占用情况或重新配置 MySQL 端口。&lt;/p&gt;
&lt;h3&gt;PowerShell 提示 mysql 不是可识别的命令&lt;a href=&quot;#powershell-提示-mysql-不是可识别的命令&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;这通常说明 MySQL 的 &lt;code&gt;bin&lt;/code&gt; 目录没有加入系统 &lt;code&gt;Path&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;不修改环境变量也可以直接使用，先进入 MySQL 的 &lt;code&gt;bin&lt;/code&gt; 目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;cd &lt;/span&gt;&lt;span&gt;&quot;C:\Program Files\MySQL\MySQL Server 8.4\bin&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;.\mysql &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;u root &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;p&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;test_db 或 student 没有显示&lt;a href=&quot;#test_db-或-student-没有显示&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 Navicat 左侧连接或数据库上右键选择“刷新”，或者重新打开 &lt;code&gt;MySQL84&lt;/code&gt; 连接。&lt;/p&gt;
&lt;p&gt;也可以在终端中依次检查：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;SHOW DATABASES;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;USE&lt;/span&gt;&lt;span&gt; test_db;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;SHOW TABLES;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;完成后的基础操作流程&lt;a href=&quot;#完成后的基础操作流程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;完成以上步骤后，应该已经能够：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 Windows 10 / 11 上安装并初始化 MySQL Community Server 8.4.11 LTS&lt;/li&gt;
&lt;li&gt;理解 &lt;code&gt;MySQL84&lt;/code&gt; Windows 服务的作用，并能够启动或停止服务&lt;/li&gt;
&lt;li&gt;使用 Navicat Premium 17 连接本机 MySQL&lt;/li&gt;
&lt;li&gt;创建数据库和数据表&lt;/li&gt;
&lt;li&gt;使用 &lt;code&gt;INSERT&lt;/code&gt; 写入数据&lt;/li&gt;
&lt;li&gt;使用 &lt;code&gt;SELECT&lt;/code&gt; 查询数据&lt;/li&gt;
&lt;li&gt;使用 PowerShell 登录 MySQL 并执行基础 SQL 命令&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;p&gt;日常练习时，可以把整个流程记成：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;启动 &lt;code&gt;MySQL84&lt;/code&gt; → 登录 MySQL → 选择 / 创建数据库 → 创建表 → 插入数据 → 查询数据&lt;/strong&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;完成这些基础操作后，就可以继续学习 SQL、数据库设计，以及 Java / Python 项目连接 MySQL。&lt;/p&gt;</content:encoded><category>category:实验室</category><category>tag:MySQL</category><category>tag:Navicat</category></item><item><title>华夏云智能监控服务管理平台</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/demo/hua-xia-yun-zhi-neng-jian-kong-fu-wu-guan-li-ping-tai</link><guid isPermaLink="false">learn/hyxy/demo/hua-xia-yun-zhi-neng-jian-kong-fu-wu-guan-li-ping-tai</guid><description>华夏云智能监控服务管理平台的界面及仓库地址</description><pubDate>Fri, 07 Aug 2026 05:51:06 GMT</pubDate><content:encoded>&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260831170322176.png&quot; alt=&quot;image-20260807140141105&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260807140141105&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div&gt;
  &lt;a href=&quot;https://github.com/qzh200/hyxy_demo&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://github.com/fluidicon.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;github.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;GitHub - qzh200/hyxy_demo&lt;/h3&gt;
        &lt;p&gt;Contribute to qzh200/hyxy_demo development by creating an account on GitHub.&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://github.com/qzh200/hyxy_demo&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://opengraph.githubassets.com/512bcdf7e7d2864ab340a7e1b46e74572395bffc0d566798cfd54f37597f78d2/qzh200/hyxy_demo&quot; alt=&quot;GitHub - qzh200/hyxy_demo&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:demo</category></item><item><title>SpringSecurity</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/framework/springsecurity</link><guid isPermaLink="false">learn/hyxy/framework/springsecurity</guid><description>SpringSecurity6 企业级安全框架
Spring Security 基础
什么是 Spring Security
Spring Security 是 Spring 生态中的安全框架，主要用于处理 Servlet 应用和响应式应用中的身份认证、访问授权及常见安全防护。
与 Apache</description><pubDate>Mon, 03 Aug 2026 02:03:20 GMT</pubDate><content:encoded>&lt;h1&gt;SpringSecurity6 企业级安全框架&lt;a href=&quot;#springsecurity6-企业级安全框架&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Spring Security 基础&lt;a href=&quot;#spring-security-基础&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;什么是 Spring Security&lt;a href=&quot;#什么是-spring-security&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Spring Security 是 Spring 生态中的安全框架，主要用于处理 Servlet 应用和响应式应用中的身份认证、访问授权及常见安全防护。&lt;/p&gt;
&lt;p&gt;与 Apache Shiro 相比，Spring Security 与 Spring Boot、Spring MVC、OAuth 2.0 等组件的集成更紧密，扩展点也更丰富。框架能力较多，因此学习时应先掌握过滤器链、认证对象和授权规则等核心概念。&lt;/p&gt;
&lt;h3&gt;认证与授权&lt;a href=&quot;#认证与授权&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;企业应用通常需要解决两个核心问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;身份认证（Authentication）&lt;/strong&gt;：确认当前访问者是谁，以及其身份是否合法。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;访问授权（Authorization）&lt;/strong&gt;：确认已经通过认证的用户是否有权访问某项资源或执行某个操作。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以在线教育平台为例：&lt;/p&gt;





















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;用户类型&lt;/th&gt;&lt;th&gt;允许执行的操作&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;学生&lt;/td&gt;&lt;td&gt;查看课程&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;教师&lt;/td&gt;&lt;td&gt;发布课程&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;管理员&lt;/td&gt;&lt;td&gt;删除用户&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;认证解决“你是谁”，授权解决“你能做什么”。&lt;/p&gt;
&lt;h3&gt;Spring Security 的主要能力&lt;a href=&quot;#spring-security-的主要能力&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Spring Security 的常见能力包括：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;用户名密码认证、证书认证、一次性令牌认证等身份认证机制。&lt;/li&gt;
&lt;li&gt;URL 级别与方法级别的访问授权。&lt;/li&gt;
&lt;li&gt;密码编码与校验。&lt;/li&gt;
&lt;li&gt;会话管理、固定会话攻击防护和并发会话控制。&lt;/li&gt;
&lt;li&gt;CSRF 防护、安全响应头等 Web 安全能力。&lt;/li&gt;
&lt;li&gt;OAuth 2.0 客户端、资源服务器和 OpenID Connect 集成。&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;p&gt;XSS 主要需要通过输出编码、内容安全策略和前端安全开发规范进行防护。Spring Security 可以配置部分安全响应头，但不能替代业务层面的 XSS 防护。&lt;/p&gt;
&lt;/div&gt;
&lt;h4&gt;CSRF&lt;a href=&quot;#csrf&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;CSRF 是跨站请求伪造。攻击者诱导已经登录合法站点的用户访问恶意页面，浏览器可能自动携带合法站点的 Cookie，从而使合法站点误以为请求由用户本人发起。&lt;/p&gt;
&lt;h4&gt;XSS&lt;a href=&quot;#xss&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;XSS 是跨站脚本攻击。攻击者设法将恶意脚本注入网页，其他用户访问页面时，浏览器执行该脚本，可能造成信息窃取、身份冒用或页面篡改。&lt;/p&gt;
&lt;h3&gt;Session 模式与 Token 模式&lt;a href=&quot;#session-模式与-token-模式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Spring Security 同时支持有状态和无状态认证。前后端分离并不意味着只能使用 Token，但在分布式 API 中，使用 Bearer Token 的无状态方案较为常见。&lt;/p&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;对比项&lt;/th&gt;&lt;th&gt;Session 有状态认证&lt;/th&gt;&lt;th&gt;Token 无状态认证&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;状态位置&lt;/td&gt;&lt;td&gt;服务端保存会话，客户端通常保存会话 Cookie&lt;/td&gt;&lt;td&gt;服务端通常不保存登录会话，客户端携带访问令牌&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;集群部署&lt;/td&gt;&lt;td&gt;需要会话复制、共享存储或粘性会话&lt;/td&gt;&lt;td&gt;各节点可独立验证令牌&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;浏览器自动携带&lt;/td&gt;&lt;td&gt;Cookie 通常由浏览器自动携带&lt;/td&gt;&lt;td&gt;&lt;code&gt;Authorization&lt;/code&gt; 请求头通常由客户端代码主动添加&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;注销与撤销&lt;/td&gt;&lt;td&gt;服务端删除会话即可立即失效&lt;/td&gt;&lt;td&gt;需要短有效期、黑名单或令牌版本等机制&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;典型场景&lt;/td&gt;&lt;td&gt;服务端渲染网站、同源 Web 应用&lt;/td&gt;&lt;td&gt;前后端分离 API、微服务资源服务器&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;
&lt;p&gt;将 Token 存入 &lt;code&gt;localStorage&lt;/code&gt; 会增加 Token 被 XSS 窃取的风险。生产系统应根据威胁模型选择内存、受保护 Cookie 或其他存储方案。若使用浏览器自动携带的 Cookie，仍需评估并配置 CSRF 防护。&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;核心架构&lt;a href=&quot;#核心架构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260803100132973.png&quot; alt=&quot;image-001&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-001&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Spring Security 的 Servlet 安全能力建立在过滤器链之上。请求进入业务控制器之前，会先经过 Spring Security 选择的 &lt;code&gt;SecurityFilterChain&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;常见核心组件如下：&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;组件&lt;/th&gt;&lt;th&gt;作用&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SecurityFilterChain&lt;/code&gt;&lt;/td&gt;&lt;td&gt;声明当前请求需要执行的安全过滤器&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;FilterChainProxy&lt;/code&gt;&lt;/td&gt;&lt;td&gt;根据请求匹配并执行相应的 &lt;code&gt;SecurityFilterChain&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Authentication&lt;/code&gt;&lt;/td&gt;&lt;td&gt;表示认证请求或当前已认证主体&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;AuthenticationManager&lt;/code&gt;&lt;/td&gt;&lt;td&gt;定义认证入口&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;AuthenticationProvider&lt;/code&gt;&lt;/td&gt;&lt;td&gt;执行某一种具体认证方式&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;UserDetailsService&lt;/code&gt;&lt;/td&gt;&lt;td&gt;按用户名加载用户信息&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;PasswordEncoder&lt;/code&gt;&lt;/td&gt;&lt;td&gt;编码密码并校验密码&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SecurityContext&lt;/code&gt;&lt;/td&gt;&lt;td&gt;保存当前请求关联的 &lt;code&gt;Authentication&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SecurityContextHolder&lt;/code&gt;&lt;/td&gt;&lt;td&gt;提供访问 &lt;code&gt;SecurityContext&lt;/code&gt; 的统一入口&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

面试题：Spring Security 的主要作用是什么？
&lt;div&gt;
&lt;p&gt;Spring Security 主要解决应用中的身份认证和访问授权问题，并提供密码编码、会话管理、CSRF 防护、安全响应头以及 OAuth 2.0 集成等安全能力。&lt;/p&gt;
&lt;/div&gt;

&lt;h2&gt;Spring Boot 3 整合 Spring Security&lt;a href=&quot;#spring-boot-3-整合-spring-security&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;环境要求&lt;a href=&quot;#环境要求&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;本课程示例使用以下环境：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Spring Boot 3.3+&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Java 17+&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Spring Security 6&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Maven&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Vue 3&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;引入依赖&lt;a href=&quot;#引入依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-web&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-security&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;编写第一个接口&lt;a href=&quot;#编写第一个接口&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequestMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/user&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; UserController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/hello&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;hello&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; &quot;hello security&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;启动项目后访问 &lt;code&gt;http://localhost:8080/user/hello&lt;/code&gt;。在没有自定义安全配置时，Spring Boot 会为 Web 应用启用默认安全配置，并显示登录页面。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260803100137520.jpg&quot; alt=&quot;image-002&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-002&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;默认用户&lt;a href=&quot;#默认用户&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;当项目中没有自定义 &lt;code&gt;UserDetailsService&lt;/code&gt;、&lt;code&gt;AuthenticationProvider&lt;/code&gt; 等认证配置时，Spring Boot 通常会创建默认用户：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;username: user&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;password: 启动时随机生成&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;随机密码会输出到控制台。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260803100142433.jpg&quot; alt=&quot;image-003&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-003&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;自定义默认用户名和密码&lt;a href=&quot;#自定义默认用户名和密码&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;spring&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  security&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    user&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;admin&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      password&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;123456&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;该配置适合入门演示，不适合生产环境。生产系统应从数据库、LDAP 或外部身份服务加载用户，并使用 &lt;code&gt;PasswordEncoder&lt;/code&gt; 保存密码摘要。&lt;/p&gt;
&lt;h3&gt;默认登录页面的形成过程&lt;a href=&quot;#默认登录页面的形成过程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在默认配置下，可将启动和访问过程概括为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Spring Boot 启动&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 加载 Spring Security 自动配置&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 创建安全过滤器链&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 请求被过滤器链拦截&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 发现请求尚未认证&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 进入登录流程或返回认证响应&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

面试题：为什么 Spring Security 不只使用 Controller 拦截请求？
&lt;div&gt;
&lt;p&gt;Spring Security 的 Servlet 支持建立在 &lt;code&gt;Filter&lt;/code&gt; 机制之上。过滤器位于 &lt;code&gt;DispatcherServlet&lt;/code&gt; 和控制器之前，可以在请求进入业务层之前完成认证、授权和安全上下文管理。&lt;/p&gt;
&lt;p&gt;典型顺序可以简化为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Servlet Filter → DispatcherServlet → HandlerInterceptor → Controller&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2&gt;Spring Security 核心原理&lt;a href=&quot;#spring-security-核心原理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;学习目标&lt;a href=&quot;#学习目标&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;完成本章后，应能够：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;理解 Spring Security 的整体请求流程。&lt;/li&gt;
&lt;li&gt;掌握 &lt;code&gt;SecurityFilterChain&lt;/code&gt; 的工作机制。&lt;/li&gt;
&lt;li&gt;理解 &lt;code&gt;Authentication&lt;/code&gt; 的两种主要用途。&lt;/li&gt;
&lt;li&gt;掌握 &lt;code&gt;AuthenticationManager&lt;/code&gt; 与 &lt;code&gt;AuthenticationProvider&lt;/code&gt; 的关系。&lt;/li&gt;
&lt;li&gt;理解 &lt;code&gt;SecurityContext&lt;/code&gt; 与 &lt;code&gt;SecurityContextHolder&lt;/code&gt; 的职责。&lt;/li&gt;
&lt;li&gt;分析用户名密码认证的主要执行步骤。&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;基于 Filter 的安全处理&lt;a href=&quot;#基于-filter-的安全处理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在传统 Spring MVC 应用中，请求流程可以简化为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;客户端请求&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ Servlet Filter&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ DispatcherServlet&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ HandlerInterceptor&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ Controller&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ DAO&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ Database&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Spring Security 选择过滤器作为 Servlet 安全入口，使认证和授权可以在业务代码执行前完成。&lt;/p&gt;
&lt;p&gt;例如，用户请求 &lt;code&gt;GET /api/user/delete/1&lt;/code&gt; 时，安全过滤器链会先判断用户是否已经认证以及是否具有删除权限。校验失败时，请求不会进入目标控制器。&lt;/p&gt;
&lt;h3&gt;SecurityFilterChain&lt;a href=&quot;#securityfilterchain&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;SecurityFilterChain&lt;/code&gt; 表示一组用于处理安全任务的过滤器。一个应用可以声明多个安全过滤器链，每条链负责不同的请求范围。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260803100144699.png&quot; alt=&quot;image-004&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-004&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;DelegatingFilterProxy 与 FilterChainProxy&lt;a href=&quot;#delegatingfilterproxy-与-filterchainproxy&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Spring Security 的 Servlet 请求转发关系可以概括为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;DelegatingFilterProxy&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ FilterChainProxy&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 匹配到的 SecurityFilterChain&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 链内的 Security Filter&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260803100233299.jpg&quot; alt=&quot;image-005&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-005&lt;/figcaption&gt;&lt;/figure&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;DelegatingFilterProxy&lt;/code&gt; 注册在 Servlet 容器中，负责把过滤工作委托给 Spring 容器管理的 &lt;code&gt;Filter&lt;/code&gt; Bean。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FilterChainProxy&lt;/code&gt; 是 Spring Security 的核心入口，会根据当前请求匹配合适的 &lt;code&gt;SecurityFilterChain&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;被选中的 &lt;code&gt;SecurityFilterChain&lt;/code&gt; 按顺序执行其中的安全过滤器。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;过滤器的具体组成取决于配置。常见过滤器包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SecurityContextHolderFilter&lt;/code&gt;：加载并管理安全上下文。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CsrfFilter&lt;/code&gt;：启用 CSRF 时校验 CSRF Token。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UsernamePasswordAuthenticationFilter&lt;/code&gt;：启用表单登录时处理用户名密码登录请求。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BearerTokenAuthenticationFilter&lt;/code&gt;：配置 OAuth 2.0 资源服务器时处理 Bearer Token。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AnonymousAuthenticationFilter&lt;/code&gt;：为匿名请求提供匿名 &lt;code&gt;Authentication&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ExceptionTranslationFilter&lt;/code&gt;：把认证和授权异常转换为相应处理流程。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AuthorizationFilter&lt;/code&gt;：执行请求级授权判断。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;p&gt;部分旧版架构图中会出现 &lt;code&gt;FilterSecurityInterceptor&lt;/code&gt;。在 Spring Security 6 的常用配置中，请求授权通常由 &lt;code&gt;AuthorizationFilter&lt;/code&gt; 完成。实际过滤器列表应以项目启动日志或调试输出为准。&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;Authentication 认证模型&lt;a href=&quot;#authentication-认证模型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260803100149550.png&quot; alt=&quot;image-006&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-006&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;Authentication 的作用&lt;a href=&quot;#authentication-的作用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;Authentication&lt;/code&gt; 有两种主要用途：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;作为待认证凭证提交给 &lt;code&gt;AuthenticationManager&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;表示当前已经通过认证的主体，并保存到 &lt;code&gt;SecurityContext&lt;/code&gt; 中。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;接口中的常用方法如下：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; Authentication&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; Principal&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Serializable&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    Object &lt;/span&gt;&lt;span&gt;getPrincipal&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    Object &lt;/span&gt;&lt;span&gt;getCredentials&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    Collection&amp;lt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; GrantedAuthority&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;getAuthorities&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    boolean&lt;/span&gt;&lt;span&gt; isAuthenticated&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;作用&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;getPrincipal()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;返回主体，用户名密码认证成功后通常为 &lt;code&gt;UserDetails&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;getCredentials()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;返回凭证，通常为密码；认证成功后可能被清除&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;getAuthorities()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;返回角色、权限或作用域集合&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;isAuthenticated()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;表示当前对象是否已经通过认证&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;认证前后的状态&lt;a href=&quot;#认证前后的状态&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;登录前创建的 &lt;code&gt;UsernamePasswordAuthenticationToken&lt;/code&gt; 通常只包含用户名和密码，并处于未认证状态：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;UsernamePasswordAuthenticationToken&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── principal: admin&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── credentials: 123456&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── authorities: []&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└── authenticated: false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;认证成功后返回的新对象通常包含用户详情和权限，并处于已认证状态：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;UsernamePasswordAuthenticationToken&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── principal: UserDetails&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── credentials: null&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── authorities: [ROLE_ADMIN, permission:query]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└── authenticated: true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不要通过不安全方式把任意未验证对象直接标记为已认证状态。&lt;/p&gt;
&lt;h3&gt;AuthenticationManager 与 AuthenticationProvider&lt;a href=&quot;#authenticationmanager-与-authenticationprovider&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;AuthenticationManager&lt;/code&gt; 定义统一认证入口：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Authentication &lt;/span&gt;&lt;span&gt;authenticate&lt;/span&gt;&lt;span&gt;(Authentication authentication)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        throws AuthenticationException;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;ProviderManager&lt;/code&gt; 是最常见的 &lt;code&gt;AuthenticationManager&lt;/code&gt; 实现。它会依次询问多个 &lt;code&gt;AuthenticationProvider&lt;/code&gt;，由支持当前 &lt;code&gt;Authentication&lt;/code&gt; 类型的 Provider 执行认证。&lt;/p&gt;
&lt;p&gt;典型用户名密码认证流程如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Authentication&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ AuthenticationManager&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ ProviderManager&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ DaoAuthenticationProvider&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ UserDetailsService&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ PasswordEncoder&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不同认证方式可以使用不同 Provider。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DaoAuthenticationProvider&lt;/code&gt; 处理数据库用户名密码认证。&lt;/li&gt;
&lt;li&gt;OAuth 2.0 资源服务器中的 &lt;code&gt;JwtAuthenticationProvider&lt;/code&gt; 处理 JWT Bearer Token。&lt;/li&gt;
&lt;li&gt;自定义 &lt;code&gt;AuthenticationProvider&lt;/code&gt; 可以处理短信验证码等业务凭证。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;UserDetailsService&lt;a href=&quot;#userdetailsservice&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Spring Security 不知道用户保存在哪里，因此通过 &lt;code&gt;UserDetailsService&lt;/code&gt; 抽象用户查询过程。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; UserDetailsService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    UserDetails &lt;/span&gt;&lt;span&gt;loadUserByUsername&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;username&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            throws&lt;/span&gt;&lt;span&gt; UsernameNotFoundException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;用户信息可以来自 MySQL、Redis、LDAP 或其他用户中心。&lt;/p&gt;
&lt;p&gt;下面是一个简化示例：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequiredArgsConstructor&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; UserService&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; UserDetailsService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; UserMapper userMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; UserDetails &lt;/span&gt;&lt;span&gt;loadUserByUsername&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;username&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        User user &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; userMapper.&lt;/span&gt;&lt;span&gt;findByUsername&lt;/span&gt;&lt;span&gt;(username);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (user &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            throw&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; UsernameNotFoundException&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;账号不存在&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; org.springframework.security.core.userdetails.User&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;withUsername&lt;/span&gt;&lt;span&gt;(user.&lt;/span&gt;&lt;span&gt;getUsername&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;password&lt;/span&gt;&lt;span&gt;(user.&lt;/span&gt;&lt;span&gt;getPassword&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;roles&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;USER&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;SecurityContext 与 SecurityContextHolder&lt;a href=&quot;#securitycontext-与-securitycontextholder&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;SecurityContext&lt;/code&gt; 保存当前认证对象，&lt;code&gt;SecurityContextHolder&lt;/code&gt; 提供对当前安全上下文的访问入口。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Authentication authentication &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; SecurityContextHolder&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;getContext&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;getAuthentication&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在 Servlet 应用中，&lt;code&gt;SecurityContextHolder&lt;/code&gt; 默认使用 &lt;code&gt;ThreadLocal&lt;/code&gt; 策略，使同一请求线程中的代码可以读取当前用户。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ThreadLocal&lt;/code&gt; 只是默认策略，并不表示一个请求在所有情况下都始终使用同一线程。异步任务、线程池和响应式编程需要使用相应的上下文传播机制。&lt;/p&gt;

面试题：SecurityContext 为什么默认使用 ThreadLocal？
&lt;div&gt;
&lt;p&gt;默认 Servlet 请求通常在线程中处理。使用 &lt;code&gt;ThreadLocal&lt;/code&gt; 可以让同一线程中的代码直接获取当前认证信息，避免层层传递参数，并隔离不同请求线程的安全上下文。Spring Security 会在请求结束后清理上下文，避免线程复用造成身份泄露。&lt;/p&gt;
&lt;/div&gt;

&lt;h3&gt;用户名密码登录流程&lt;a href=&quot;#用户名密码登录流程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;启用表单登录时，典型流程如下：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;POST /login&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ UsernamePasswordAuthenticationFilter&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 创建未认证 UsernamePasswordAuthenticationToken&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ AuthenticationManager&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ ProviderManager&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ DaoAuthenticationProvider&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ UserDetailsService 查询用户&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ PasswordEncoder 校验密码&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 返回已认证 Authentication&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 保存到 SecurityContext&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 执行认证成功处理&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;本课程后续使用自定义 &lt;code&gt;LoginController&lt;/code&gt; 调用 &lt;code&gt;AuthenticationManager&lt;/code&gt;。这种情况下，登录请求不会经过 &lt;code&gt;UsernamePasswordAuthenticationFilter&lt;/code&gt;，控制器负责生成 JWT；后续请求则由自定义 JWT 过滤器解析令牌并建立当前请求的 &lt;code&gt;SecurityContext&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;本章总结&lt;a href=&quot;#本章总结&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;组件&lt;/th&gt;&lt;th&gt;作用&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SecurityFilterChain&lt;/code&gt;&lt;/td&gt;&lt;td&gt;定义请求需要执行的安全过滤器&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;FilterChainProxy&lt;/code&gt;&lt;/td&gt;&lt;td&gt;匹配并执行安全过滤器链&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Authentication&lt;/code&gt;&lt;/td&gt;&lt;td&gt;表示认证请求或当前认证主体&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;AuthenticationManager&lt;/code&gt;&lt;/td&gt;&lt;td&gt;提供统一认证入口&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ProviderManager&lt;/code&gt;&lt;/td&gt;&lt;td&gt;调度多个 &lt;code&gt;AuthenticationProvider&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;AuthenticationProvider&lt;/code&gt;&lt;/td&gt;&lt;td&gt;执行具体认证逻辑&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;UserDetailsService&lt;/code&gt;&lt;/td&gt;&lt;td&gt;加载用户信息&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;PasswordEncoder&lt;/code&gt;&lt;/td&gt;&lt;td&gt;编码并校验密码&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SecurityContext&lt;/code&gt;&lt;/td&gt;&lt;td&gt;保存当前认证对象&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SecurityContextHolder&lt;/code&gt;&lt;/td&gt;&lt;td&gt;访问当前安全上下文&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

面试题：Authentication 与 UserDetails 有什么区别？
&lt;div&gt;
&lt;p&gt;&lt;code&gt;UserDetails&lt;/code&gt; 描述从用户数据源加载出的账号信息，例如用户名、密码摘要、账号状态和权限。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Authentication&lt;/code&gt; 既可以表示待认证凭证，也可以表示已经通过认证的当前主体。认证成功后，其 &lt;code&gt;principal&lt;/code&gt; 通常是一个 &lt;code&gt;UserDetails&lt;/code&gt; 实例。&lt;/p&gt;
&lt;/div&gt;

&lt;h2&gt;前后端分离身份认证&lt;a href=&quot;#前后端分离身份认证&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260803100153259.png&quot; alt=&quot;image-007&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-007&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;本章采用以下方案：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;用户名密码登录&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ AuthenticationManager 校验&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 服务端签发 JWT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 客户端使用 Authorization 请求头携带 JWT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ JWT 过滤器验签并建立 SecurityContext&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ Spring Security 执行访问授权&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;数据库表结构&lt;a href=&quot;#数据库表结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;下面的示例保留用户、角色、权限和菜单关系。角色表增加稳定的英文 &lt;code&gt;role_key&lt;/code&gt;，用于生成 &lt;code&gt;ROLE_ADMIN&lt;/code&gt;、&lt;code&gt;ROLE_USER&lt;/code&gt; 等权限标识。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;DROP&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; IF&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; `t_menu_role`&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;DROP&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; IF&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; `t_role_permission`&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;DROP&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; IF&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; `t_menu`&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;DROP&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; IF&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; `t_permission`&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;DROP&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; IF&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; `t_user`&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;DROP&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; IF&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; `t_role`&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; `&lt;/span&gt;&lt;span&gt;t_menu&lt;/span&gt;&lt;span&gt;` (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `id`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; NOT NULL&lt;/span&gt;&lt;span&gt; AUTO_INCREMENT COMMENT &lt;/span&gt;&lt;span&gt;&apos;主键&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `name`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt; COMMENT &lt;/span&gt;&lt;span&gt;&apos;菜单名称&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `icon`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt; COMMENT &lt;/span&gt;&lt;span&gt;&apos;菜单图标&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `url`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt; COMMENT &lt;/span&gt;&lt;span&gt;&apos;菜单 URL&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `pid`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; DEFAULT&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt; COMMENT &lt;/span&gt;&lt;span&gt;&apos;父菜单 ID&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `remark`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt; COMMENT &lt;/span&gt;&lt;span&gt;&apos;备注&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `level`&lt;/span&gt;&lt;span&gt; INT&lt;/span&gt;&lt;span&gt; DEFAULT&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt; COMMENT &lt;/span&gt;&lt;span&gt;&apos;菜单层级&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `is_link`&lt;/span&gt;&lt;span&gt; TINYINT&lt;/span&gt;&lt;span&gt; DEFAULT&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt; COMMENT &lt;/span&gt;&lt;span&gt;&apos;是否可跳转&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    PRIMARY KEY&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`id`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;) ENGINE &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; InnoDB &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; CHARSET &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; utf8mb4;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; `&lt;/span&gt;&lt;span&gt;t_role&lt;/span&gt;&lt;span&gt;` (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `id`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; NOT NULL&lt;/span&gt;&lt;span&gt; AUTO_INCREMENT,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `role_name`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `role_key`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;64&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    PRIMARY KEY&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`id`&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    UNIQUE&lt;/span&gt;&lt;span&gt; KEY&lt;/span&gt;&lt;span&gt; `uk_role_key`&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`role_key`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;) ENGINE &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; InnoDB &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; CHARSET &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; utf8mb4;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; `&lt;/span&gt;&lt;span&gt;t_permission&lt;/span&gt;&lt;span&gt;` (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `id`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; NOT NULL&lt;/span&gt;&lt;span&gt; AUTO_INCREMENT,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `permission_name`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `permission_key`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    PRIMARY KEY&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`id`&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    UNIQUE&lt;/span&gt;&lt;span&gt; KEY&lt;/span&gt;&lt;span&gt; `uk_permission_key`&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`permission_key`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;) ENGINE &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; InnoDB &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; CHARSET &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; utf8mb4;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; `&lt;/span&gt;&lt;span&gt;t_user&lt;/span&gt;&lt;span&gt;` (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `id`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; NOT NULL&lt;/span&gt;&lt;span&gt; AUTO_INCREMENT,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `username`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `password`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `role_id`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `nickname`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `email`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `phone`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `freeze`&lt;/span&gt;&lt;span&gt; TINYINT&lt;/span&gt;&lt;span&gt; DEFAULT&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `dept_id`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; DEFAULT&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `remark`&lt;/span&gt;&lt;span&gt; VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;255&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `insert_time`&lt;/span&gt;&lt;span&gt; DATETIME&lt;/span&gt;&lt;span&gt; DEFAULT&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    PRIMARY KEY&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`id`&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    UNIQUE&lt;/span&gt;&lt;span&gt; KEY&lt;/span&gt;&lt;span&gt; `uk_username`&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`username`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;) ENGINE &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; InnoDB &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; CHARSET &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; utf8mb4;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; `&lt;/span&gt;&lt;span&gt;t_role_permission&lt;/span&gt;&lt;span&gt;` (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `id`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; NOT NULL&lt;/span&gt;&lt;span&gt; AUTO_INCREMENT,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `role_id`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `permission_id`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    PRIMARY KEY&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`id`&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    UNIQUE&lt;/span&gt;&lt;span&gt; KEY&lt;/span&gt;&lt;span&gt; `uk_role_permission`&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`role_id`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`permission_id`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;) ENGINE &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; InnoDB &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; CHARSET &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; utf8mb4;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; `&lt;/span&gt;&lt;span&gt;t_menu_role&lt;/span&gt;&lt;span&gt;` (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `id`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; NOT NULL&lt;/span&gt;&lt;span&gt; AUTO_INCREMENT,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `menu_id`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    `role_id`&lt;/span&gt;&lt;span&gt; BIGINT&lt;/span&gt;&lt;span&gt; NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    PRIMARY KEY&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`id`&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    UNIQUE&lt;/span&gt;&lt;span&gt; KEY&lt;/span&gt;&lt;span&gt; `uk_menu_role`&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`menu_id`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`role_id`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;) ENGINE &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; InnoDB &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; CHARSET &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; utf8mb4;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;START TRANSACTION&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;INSERT INTO&lt;/span&gt;&lt;span&gt; `t_role`&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`id`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`role_name`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`role_key`&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;系统管理员&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;ADMIN&apos;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;普通用户&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;USER&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;INSERT INTO&lt;/span&gt;&lt;span&gt; `t_permission`&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`id`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`permission_name`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`permission_key`&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;查询&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;permission:query&apos;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;新增&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;permission:insert&apos;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;修改&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;permission:update&apos;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;删除&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;permission:delete&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;INSERT INTO&lt;/span&gt;&lt;span&gt; `t_role_permission`&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`id`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`role_id`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`permission_id`&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;51&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;52&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;53&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;61&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;INSERT INTO&lt;/span&gt;&lt;span&gt; `t_menu`&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`id`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`name`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`icon`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`url`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`pid`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`remark`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`level`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`is_link`&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;系统设置&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;layui-icon-fire&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;分类管理&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;layui-icon-name&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;category/list&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;商品管理&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;layui-icon-service&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;商品列表&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;layui-icon-rate&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;asset-info/list&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;INSERT INTO&lt;/span&gt;&lt;span&gt; `t_menu_role`&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;`id`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`menu_id`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`role_id`&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;INSERT INTO&lt;/span&gt;&lt;span&gt; `t_user`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;`id`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`username`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`password`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`role_id`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`nickname`&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;`insert_time`&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;admin&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &apos;$2a$10$t9BSP6hInmZm5RJocXVMdOLXzVXh4wgiBaYrM6iUslsrb.5z.eYce&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;超级管理员&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;2021-05-26 14:41:06&apos;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    (&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;normal&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &apos;$2a$10$Mv1ruD0gHy9Uq73SbfH80ep1McuJNZiJCjM3BpxAJVr9pt34iwWlS&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;普通用户&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;NULL&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;COMMIT&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;后端依赖&lt;a href=&quot;#后端依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-web&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-security&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.baomidou&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-plus-spring-boot3-starter&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.5.6&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;runtime&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.projectlombok&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;lombok&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;gt;true&amp;lt;/&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;io.jsonwebtoken&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;jjwt-api&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;0.12.5&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;io.jsonwebtoken&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;jjwt-impl&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;0.12.5&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;runtime&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;io.jsonwebtoken&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;jjwt-jackson&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;0.12.5&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;runtime&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-test&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;test&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;同一项目中的 JJWT 模块应使用相同版本。&lt;/p&gt;
&lt;h3&gt;前端请求拦截器&lt;a href=&quot;#前端请求拦截器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;登录成功后，前端保存访问令牌，并在后续请求的 &lt;code&gt;Authorization&lt;/code&gt; 请求头中携带 &lt;code&gt;Bearer Token&lt;/code&gt;。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; axios &lt;/span&gt;&lt;span&gt;from&lt;/span&gt;&lt;span&gt; &apos;axios&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; service&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; axios.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  baseURL: &lt;/span&gt;&lt;span&gt;&apos;http://localhost:8080&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  timeout: &lt;/span&gt;&lt;span&gt;5000&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;service.interceptors.request.&lt;/span&gt;&lt;span&gt;use&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  config&lt;/span&gt;&lt;span&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; token&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; localStorage.&lt;/span&gt;&lt;span&gt;getItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;token&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (token) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      config.headers.Authorization &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; `Bearer ${&lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt;}`&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  error&lt;/span&gt;&lt;span&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; Promise&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;reject&lt;/span&gt;&lt;span&gt;(error)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;service.interceptors.response.&lt;/span&gt;&lt;span&gt;use&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  response&lt;/span&gt;&lt;span&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; response.data,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  error&lt;/span&gt;&lt;span&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    const&lt;/span&gt;&lt;span&gt; status&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; error.response?.status&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (status &lt;/span&gt;&lt;span&gt;===&lt;/span&gt;&lt;span&gt; 401&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      localStorage.&lt;/span&gt;&lt;span&gt;removeItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;token&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      window.location.href &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &apos;/login&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; Promise&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;reject&lt;/span&gt;&lt;span&gt;(error)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;export&lt;/span&gt;&lt;span&gt; default&lt;/span&gt;&lt;span&gt; service&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;HTTP 状态码应与业务响应体中的业务码分开处理：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;401 Unauthorized&lt;/code&gt; 表示未认证、Token 无效或 Token 已过期。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;403 Forbidden&lt;/code&gt; 表示已经认证，但没有访问权限。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Security 核心配置&lt;a href=&quot;#security-核心配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; jakarta.servlet.http.HttpServletResponse;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.context.annotation.Bean;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.context.annotation.Configuration;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.http.HttpHeaders;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.http.HttpMethod;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.http.MediaType;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.authentication.AuthenticationManager;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.config.Customizer;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.config.annotation.web.builders.HttpSecurity;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.config.http.SessionCreationPolicy;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.crypto.password.PasswordEncoder;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.web.SecurityFilterChain;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.cors.CorsConfiguration;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.cors.CorsConfigurationSource;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.cors.UrlBasedCorsConfigurationSource;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.nio.charset.StandardCharsets;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;EnableWebSecurity&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; SecurityConfig&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; String&lt;/span&gt;&lt;span&gt;[] WHITE_LIST &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &quot;/login&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &quot;/doc.html&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &quot;/webjars/**&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &quot;/favicon.ico&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &quot;/druid/**&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &quot;/public/**&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    };&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; SecurityFilterChain &lt;/span&gt;&lt;span&gt;securityFilterChain&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            HttpSecurity &lt;/span&gt;&lt;span&gt;http&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            JwtAuthenticationFilter &lt;/span&gt;&lt;span&gt;jwtAuthenticationFilter&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Exception {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        http&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;csrf&lt;/span&gt;&lt;span&gt;(AbstractHttpConfigurer&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;disable)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;cors&lt;/span&gt;&lt;span&gt;(Customizer.&lt;/span&gt;&lt;span&gt;withDefaults&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;formLogin&lt;/span&gt;&lt;span&gt;(AbstractHttpConfigurer&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;disable)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;httpBasic&lt;/span&gt;&lt;span&gt;(AbstractHttpConfigurer&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;disable)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;sessionManagement&lt;/span&gt;&lt;span&gt;(session &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; session&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;sessionCreationPolicy&lt;/span&gt;&lt;span&gt;(SessionCreationPolicy.STATELESS))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;exceptionHandling&lt;/span&gt;&lt;span&gt;(exceptions &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; exceptions&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;authenticationEntryPoint&lt;/span&gt;&lt;span&gt;((request, response, exception) &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                            response.&lt;/span&gt;&lt;span&gt;setStatus&lt;/span&gt;&lt;span&gt;(HttpServletResponse.SC_UNAUTHORIZED);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                            response.&lt;/span&gt;&lt;span&gt;setCharacterEncoding&lt;/span&gt;&lt;span&gt;(StandardCharsets.UTF_8.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                            response.&lt;/span&gt;&lt;span&gt;setContentType&lt;/span&gt;&lt;span&gt;(MediaType.APPLICATION_JSON_VALUE);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                            response.&lt;/span&gt;&lt;span&gt;getWriter&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;write&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                    &quot;{&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;code&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;:401,&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;msg&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;未登录或令牌无效&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                            );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;accessDeniedHandler&lt;/span&gt;&lt;span&gt;((request, response, exception) &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                            response.&lt;/span&gt;&lt;span&gt;setStatus&lt;/span&gt;&lt;span&gt;(HttpServletResponse.SC_FORBIDDEN);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                            response.&lt;/span&gt;&lt;span&gt;setCharacterEncoding&lt;/span&gt;&lt;span&gt;(StandardCharsets.UTF_8.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                            response.&lt;/span&gt;&lt;span&gt;setContentType&lt;/span&gt;&lt;span&gt;(MediaType.APPLICATION_JSON_VALUE);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                            response.&lt;/span&gt;&lt;span&gt;getWriter&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;write&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                    &quot;{&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;code&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;:403,&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;msg&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;没有访问权限&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                            );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        }))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;authorizeHttpRequests&lt;/span&gt;&lt;span&gt;(authorize &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; authorize&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;requestMatchers&lt;/span&gt;&lt;span&gt;(HttpMethod.OPTIONS, &lt;/span&gt;&lt;span&gt;&quot;/**&quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;permitAll&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;requestMatchers&lt;/span&gt;&lt;span&gt;(WHITE_LIST).&lt;/span&gt;&lt;span&gt;permitAll&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;anyRequest&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;authenticated&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;addFilterBefore&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        jwtAuthenticationFilter,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        UsernamePasswordAuthenticationFilter.class&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; http.&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; CorsConfigurationSource &lt;/span&gt;&lt;span&gt;corsConfigurationSource&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        CorsConfiguration configuration &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; CorsConfiguration&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        configuration.&lt;/span&gt;&lt;span&gt;setAllowedOrigins&lt;/span&gt;&lt;span&gt;(List.&lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;http://localhost:5173&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        configuration.&lt;/span&gt;&lt;span&gt;setAllowedMethods&lt;/span&gt;&lt;span&gt;(List.&lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;GET&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;POST&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;PUT&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;DELETE&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;OPTIONS&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        ));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        configuration.&lt;/span&gt;&lt;span&gt;setAllowedHeaders&lt;/span&gt;&lt;span&gt;(List.&lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                HttpHeaders.AUTHORIZATION,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                HttpHeaders.CONTENT_TYPE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        ));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        configuration.&lt;/span&gt;&lt;span&gt;setExposedHeaders&lt;/span&gt;&lt;span&gt;(List.&lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt;(HttpHeaders.AUTHORIZATION));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        configuration.&lt;/span&gt;&lt;span&gt;setAllowCredentials&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        UrlBasedCorsConfigurationSource source &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                new&lt;/span&gt;&lt;span&gt; UrlBasedCorsConfigurationSource&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        source.&lt;/span&gt;&lt;span&gt;registerCorsConfiguration&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/**&quot;&lt;/span&gt;&lt;span&gt;, configuration);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; source;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; PasswordEncoder &lt;/span&gt;&lt;span&gt;passwordEncoder&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; BCryptPasswordEncoder&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; AuthenticationManager &lt;/span&gt;&lt;span&gt;authenticationManager&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            AuthenticationConfiguration &lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Exception {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; configuration.&lt;/span&gt;&lt;span&gt;getAuthenticationManager&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;本示例的 Token 只通过 &lt;code&gt;Authorization&lt;/code&gt; 请求头传递，且服务端不依赖浏览器 Cookie，因此关闭 CSRF。若改为 Cookie 自动携带凭证，应重新评估并启用合适的 CSRF 防护。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;@EnableWebSecurity&lt;/code&gt; 用于导入 Spring Security 的 Servlet Web 安全配置。真正的请求规则由 &lt;code&gt;SecurityFilterChain&lt;/code&gt; Bean 定义；Spring Boot Starter 负责相关自动配置和基础集成。&lt;/p&gt;
&lt;p&gt;生产环境中的 CORS 允许源必须配置为真实前端域名，不应无条件放行任意来源。&lt;/p&gt;
&lt;h3&gt;生成实体与 Mapper&lt;a href=&quot;#生成实体与-mapper&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;可使用 MyBatis Plus 逆向工程生成 &lt;code&gt;User&lt;/code&gt;、&lt;code&gt;Role&lt;/code&gt;、&lt;code&gt;Permission&lt;/code&gt;、&lt;code&gt;Menu&lt;/code&gt; 及其 Mapper。生成后仍需检查字段类型、表关联查询和空值处理，不能直接把逆向工程结果视为完整业务代码。&lt;/p&gt;
&lt;h3&gt;实现 UserDetails&lt;a href=&quot;#实现-userdetails&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.core.GrantedAuthority;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.core.authority.SimpleGrantedAuthority;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.core.userdetails.UserDetails;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.Collection;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.stream.Stream;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; UserItem&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; UserDetails&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; User user;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; permissions;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;GrantedAuthority&lt;/span&gt;&lt;span&gt;&amp;gt; authorities;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; UserItem&lt;/span&gt;&lt;span&gt;(User &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;, String &lt;/span&gt;&lt;span&gt;roleKey&lt;/span&gt;&lt;span&gt;, List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;permissions&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.user &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; user;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.permissions &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; List.&lt;/span&gt;&lt;span&gt;copyOf&lt;/span&gt;&lt;span&gt;(permissions);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.authorities &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Stream.&lt;/span&gt;&lt;span&gt;concat&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        Stream.&lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; SimpleGrantedAuthority&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;ROLE_&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; roleKey)),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        permissions.&lt;/span&gt;&lt;span&gt;stream&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(SimpleGrantedAuthority&lt;/span&gt;&lt;span&gt;::new&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(GrantedAuthority.class&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;cast)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;toList&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; User &lt;/span&gt;&lt;span&gt;getUser&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; user;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;getPermissions&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; permissions;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Collection&amp;lt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; GrantedAuthority&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;getAuthorities&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; authorities;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;getPassword&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; user.&lt;/span&gt;&lt;span&gt;getPassword&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;getUsername&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; user.&lt;/span&gt;&lt;span&gt;getUsername&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; isAccountNonExpired&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; isAccountNonLocked&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; user.&lt;/span&gt;&lt;span&gt;getFreeze&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; ||&lt;/span&gt;&lt;span&gt; user.&lt;/span&gt;&lt;span&gt;getFreeze&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; isCredentialsNonExpired&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; isEnabled&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;hasRole(&apos;ADMIN&apos;)&lt;/code&gt; 会自动检查 &lt;code&gt;ROLE_ADMIN&lt;/code&gt;，因此数据库中的稳定角色标识应保存为 &lt;code&gt;ADMIN&lt;/code&gt;，构造权限时再添加 &lt;code&gt;ROLE_&lt;/code&gt; 前缀。&lt;/p&gt;
&lt;h3&gt;实现 UserDetailsService&lt;a href=&quot;#实现-userdetailsservice&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; lombok.RequiredArgsConstructor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.core.userdetails.UserDetails;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.core.userdetails.UserDetailsService;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.core.userdetails.UsernameNotFoundException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.stereotype.Service;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequiredArgsConstructor&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; UserDetailsServiceImpl&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; UserDetailsService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; UserMapper userMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; RoleMapper roleMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; PermissionMapper permissionMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; UserDetails &lt;/span&gt;&lt;span&gt;loadUserByUsername&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;username&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        User user &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; userMapper.&lt;/span&gt;&lt;span&gt;selectOne&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                new&lt;/span&gt;&lt;span&gt; LambdaQueryWrapper&amp;lt;&lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;eq&lt;/span&gt;&lt;span&gt;(User&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getUsername, username)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;last&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;LIMIT 1&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (user &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            throw&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; UsernameNotFoundException&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;账号不存在&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Role role &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; roleMapper.&lt;/span&gt;&lt;span&gt;selectById&lt;/span&gt;&lt;span&gt;(user.&lt;/span&gt;&lt;span&gt;getRoleId&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (role &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            throw&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; UsernameNotFoundException&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;账号未配置有效角色&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; permissions &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; permissionMapper&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;selectPermissionListByRoleId&lt;/span&gt;&lt;span&gt;(user.&lt;/span&gt;&lt;span&gt;getRoleId&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;stream&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(Permission&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getPermissionKey)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;toList&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; UserItem&lt;/span&gt;&lt;span&gt;(user, role.&lt;/span&gt;&lt;span&gt;getRoleKey&lt;/span&gt;&lt;span&gt;(), permissions);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;BCrypt 密码编码&lt;a href=&quot;#bcrypt-密码编码&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;BCryptPasswordEncoder&lt;/code&gt; 使用带随机盐的自适应单向哈希算法。相同明文每次编码得到的结果通常不同，但都可以通过 &lt;code&gt;matches()&lt;/code&gt; 完成校验。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; shouldEncodeAndMatchPassword&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    PasswordEncoder encoder &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; BCryptPasswordEncoder&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    String encodedPassword &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; encoder.&lt;/span&gt;&lt;span&gt;encode&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;123456&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    boolean&lt;/span&gt;&lt;span&gt; matched &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; encoder.&lt;/span&gt;&lt;span&gt;matches&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;123456&quot;&lt;/span&gt;&lt;span&gt;, encodedPassword);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(encodedPassword);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(matched);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;密码摘要不能被“解密”回明文。登录时应使用 &lt;code&gt;matches(rawPassword, encodedPassword)&lt;/code&gt; 校验，而不是再次编码后比较字符串。&lt;/p&gt;
&lt;h3&gt;统一响应对象&lt;a href=&quot;#统一响应对象&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; record&lt;/span&gt;&lt;span&gt; Result&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; code, T data, String msg, &lt;/span&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; count) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; Result&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt;(T &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;, String &lt;/span&gt;&lt;span&gt;msg&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Result&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;, data, msg, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; Result&amp;lt;&lt;/span&gt;&lt;span&gt;Void&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;msg&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Result&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span&gt;200&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;, msg, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; Result&amp;lt;&lt;/span&gt;&lt;span&gt;Void&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;fail&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; code&lt;/span&gt;&lt;span&gt;, String &lt;/span&gt;&lt;span&gt;msg&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Result&amp;lt;&amp;gt;(code, &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;, msg, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; Result&amp;lt;&lt;/span&gt;&lt;span&gt;Void&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;fail&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;msg&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; fail&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;500&lt;/span&gt;&lt;span&gt;, msg);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;业务响应码应与 HTTP 状态码保持清晰语义。实际项目可使用 &lt;code&gt;ResponseEntity&lt;/code&gt; 或全局异常处理器统一设置 HTTP 状态。&lt;/p&gt;
&lt;h3&gt;JWT 认证过滤器&lt;a href=&quot;#jwt-认证过滤器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;自定义登录接口只负责签发 Token。后续每个受保护请求还需要解析 Token，并把认证结果放入当前请求的 &lt;code&gt;SecurityContext&lt;/code&gt;。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.jsonwebtoken.Claims;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.jsonwebtoken.JwtException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; jakarta.servlet.FilterChain;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; jakarta.servlet.ServletException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; jakarta.servlet.http.HttpServletRequest;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; jakarta.servlet.http.HttpServletResponse;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; lombok.RequiredArgsConstructor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.http.HttpHeaders;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.authentication.UsernamePasswordAuthenticationToken;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.core.GrantedAuthority;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.core.authority.SimpleGrantedAuthority;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.core.context.SecurityContext;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.core.context.SecurityContextHolder;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.stereotype.Component;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.filter.OncePerRequestFilter;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.io.IOException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequiredArgsConstructor&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; JwtAuthenticationFilter&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; OncePerRequestFilter&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; String BEARER_PREFIX &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;Bearer &quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; JwtUtil jwtUtil;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    protected&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; doFilterInternal&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            HttpServletRequest &lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            HttpServletResponse &lt;/span&gt;&lt;span&gt;response&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            FilterChain &lt;/span&gt;&lt;span&gt;filterChain&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; ServletException, IOException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String authorization &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; request.&lt;/span&gt;&lt;span&gt;getHeader&lt;/span&gt;&lt;span&gt;(HttpHeaders.AUTHORIZATION);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (authorization &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; ||&lt;/span&gt;&lt;span&gt; !&lt;/span&gt;&lt;span&gt;authorization.&lt;/span&gt;&lt;span&gt;startsWith&lt;/span&gt;&lt;span&gt;(BEARER_PREFIX)) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            filterChain.&lt;/span&gt;&lt;span&gt;doFilter&lt;/span&gt;&lt;span&gt;(request, response);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            return&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String token &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; authorization.&lt;/span&gt;&lt;span&gt;substring&lt;/span&gt;&lt;span&gt;(BEARER_PREFIX.&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span&gt;()).&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Claims claims &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; jwtUtil.&lt;/span&gt;&lt;span&gt;parseToken&lt;/span&gt;&lt;span&gt;(token);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            if&lt;/span&gt;&lt;span&gt; (SecurityContextHolder.&lt;/span&gt;&lt;span&gt;getContext&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;getAuthentication&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                List&amp;lt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&amp;gt; values &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; claims.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;permissions&quot;&lt;/span&gt;&lt;span&gt;, List.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                List&amp;lt;&lt;/span&gt;&lt;span&gt;GrantedAuthority&lt;/span&gt;&lt;span&gt;&amp;gt; authorities &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; values &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        ?&lt;/span&gt;&lt;span&gt; List.&lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        :&lt;/span&gt;&lt;span&gt; values.&lt;/span&gt;&lt;span&gt;stream&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                .&lt;/span&gt;&lt;span&gt;filter&lt;/span&gt;&lt;span&gt;(String.class&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;isInstance)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                .&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(String.class&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;cast)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                .&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(SimpleGrantedAuthority&lt;/span&gt;&lt;span&gt;::new&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                .&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(GrantedAuthority.class&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;cast)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                .&lt;/span&gt;&lt;span&gt;toList&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                UsernamePasswordAuthenticationToken authentication &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        UsernamePasswordAuthenticationToken.&lt;/span&gt;&lt;span&gt;authenticated&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                claims.&lt;/span&gt;&lt;span&gt;getSubject&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                authorities&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                SecurityContext context &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        SecurityContextHolder.&lt;/span&gt;&lt;span&gt;createEmptyContext&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                context.&lt;/span&gt;&lt;span&gt;setAuthentication&lt;/span&gt;&lt;span&gt;(authentication);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                SecurityContextHolder.&lt;/span&gt;&lt;span&gt;setContext&lt;/span&gt;&lt;span&gt;(context);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            filterChain.&lt;/span&gt;&lt;span&gt;doFilter&lt;/span&gt;&lt;span&gt;(request, response);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (JwtException | IllegalArgumentException &lt;/span&gt;&lt;span&gt;exception&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            SecurityContextHolder.&lt;/span&gt;&lt;span&gt;clearContext&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            response.&lt;/span&gt;&lt;span&gt;setStatus&lt;/span&gt;&lt;span&gt;(HttpServletResponse.SC_UNAUTHORIZED);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            response.&lt;/span&gt;&lt;span&gt;setContentType&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;application/json;charset=UTF-8&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            response.&lt;/span&gt;&lt;span&gt;getWriter&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;write&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &quot;{&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;code&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;:401,&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;msg&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;令牌无效或已过期&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;该示例直接使用 JWT 中的权限，优点是无需每次查询数据库，缺点是权限变更不会立即影响旧 Token。生产系统可以采用短时效 Token、令牌版本号、黑名单，或每次请求重新查询关键权限。&lt;/p&gt;
&lt;h3&gt;自定义登录接口&lt;a href=&quot;#自定义登录接口&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; lombok.RequiredArgsConstructor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.authentication.AuthenticationManager;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.authentication.BadCredentialsException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.authentication.LockedException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.authentication.UsernamePasswordAuthenticationToken;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.core.Authentication;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.core.GrantedAuthority;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.PostMapping;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.RequestBody;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.RestController;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.HashMap;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.Map;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequiredArgsConstructor&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; LoginController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; AuthenticationManager authenticationManager;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; MenuService menuService;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; JwtUtil jwtUtil;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PostMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/login&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Result&amp;lt;Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span&gt;login&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;RequestBody&lt;/span&gt;&lt;span&gt; LoginRequest &lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Authentication authentication &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; authenticationManager.&lt;/span&gt;&lt;span&gt;authenticate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                UsernamePasswordAuthenticationToken.&lt;/span&gt;&lt;span&gt;unauthenticated&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        request.&lt;/span&gt;&lt;span&gt;username&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        request.&lt;/span&gt;&lt;span&gt;password&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        UserItem userItem &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (UserItem) authentication.&lt;/span&gt;&lt;span&gt;getPrincipal&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        User user &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; userItem.&lt;/span&gt;&lt;span&gt;getUser&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; authorities &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; authentication.&lt;/span&gt;&lt;span&gt;getAuthorities&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;stream&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(GrantedAuthority&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getAuthority)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;toList&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String token &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; jwtUtil.&lt;/span&gt;&lt;span&gt;createToken&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                user.&lt;/span&gt;&lt;span&gt;getId&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                user.&lt;/span&gt;&lt;span&gt;getUsername&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                user.&lt;/span&gt;&lt;span&gt;getRoleId&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                authorities&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        List&amp;lt;&lt;/span&gt;&lt;span&gt;Menu&lt;/span&gt;&lt;span&gt;&amp;gt; menuList &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; menuService.&lt;/span&gt;&lt;span&gt;listByRoleId&lt;/span&gt;&lt;span&gt;(user.&lt;/span&gt;&lt;span&gt;getRoleId&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;&amp;gt; data &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; HashMap&amp;lt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        data.&lt;/span&gt;&lt;span&gt;put&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;token&quot;&lt;/span&gt;&lt;span&gt;, token);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        data.&lt;/span&gt;&lt;span&gt;put&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;user&quot;&lt;/span&gt;&lt;span&gt;, user);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        data.&lt;/span&gt;&lt;span&gt;put&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;menuList&quot;&lt;/span&gt;&lt;span&gt;, menuList);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        data.&lt;/span&gt;&lt;span&gt;put&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;authorities&quot;&lt;/span&gt;&lt;span&gt;, authorities);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; Result.&lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt;(data, &lt;/span&gt;&lt;span&gt;&quot;登录成功&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; record&lt;/span&gt;&lt;span&gt; LoginRequest&lt;/span&gt;&lt;span&gt;(String username, String password) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;认证异常建议交给全局异常处理器统一转换：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.http.HttpStatus;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.http.ResponseEntity;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.authentication.BadCredentialsException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.authentication.LockedException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.ExceptionHandler;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.RestControllerAdvice;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestControllerAdvice&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; GlobalExceptionHandler&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;ExceptionHandler&lt;/span&gt;&lt;span&gt;(BadCredentialsException.class)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; ResponseEntity&amp;lt;Result&amp;lt;&lt;/span&gt;&lt;span&gt;Void&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span&gt;handleBadCredentials&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; ResponseEntity.&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;(HttpStatus.UNAUTHORIZED)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;(Result.&lt;/span&gt;&lt;span&gt;fail&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;401&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;用户名或密码错误&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;ExceptionHandler&lt;/span&gt;&lt;span&gt;(LockedException.class)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; ResponseEntity&amp;lt;Result&amp;lt;&lt;/span&gt;&lt;span&gt;Void&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span&gt;handleLocked&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; ResponseEntity.&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;(HttpStatus.FORBIDDEN)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;body&lt;/span&gt;&lt;span&gt;(Result.&lt;/span&gt;&lt;span&gt;fail&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;403&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;账号已被冻结&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;不要把密码、密码摘要等敏感字段直接放入登录响应。可以创建专用用户响应对象，只返回前端实际需要的字段。&lt;/p&gt;
&lt;h3&gt;接口测试&lt;a href=&quot;#接口测试&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;登录成功后，响应中返回 Token、用户基本信息、菜单和权限集合。后续请求应在请求头中携带：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Authorization&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; Bearer &amp;lt;token&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260803100202553.png&quot; alt=&quot;image-008&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-008&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;权限控制实战&lt;a href=&quot;#权限控制实战&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;开启方法级授权&lt;a href=&quot;#开启方法级授权&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Spring Security 6 使用 &lt;code&gt;@EnableMethodSecurity&lt;/code&gt; 开启方法级授权。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.boot.SpringApplication;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.boot.autoconfigure.SpringBootApplication;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;SpringBootApplication&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;EnableMethodSecurity&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; SecurityApplication&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SpringApplication.&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;(SecurityApplication.class, args);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;spring-boot-starter-security&lt;/code&gt; 不会默认开启方法级授权，因此需要显式添加 &lt;code&gt;@EnableMethodSecurity&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;使用 &lt;code&gt;@PreAuthorize&lt;/code&gt;&lt;a href=&quot;#使用-preauthorize&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.security.access.prepost.PreAuthorize;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.GetMapping;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.RestController;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; PermissionController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PreAuthorize&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;hasRole(&apos;ADMIN&apos;)&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/admin&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;admin&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; &quot;管理员接口访问成功&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PreAuthorize&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;hasAuthority(&apos;permission:query&apos;)&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/user/list&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;userList&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; &quot;用户列表接口访问成功&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PreAuthorize&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;hasAnyRole(&apos;ADMIN&apos;, &apos;USER&apos;)&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/common&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;common&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; &quot;通用接口访问成功&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;常用表达式如下：&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;表达式&lt;/th&gt;&lt;th&gt;含义&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;hasRole(&apos;ADMIN&apos;)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否具有 &lt;code&gt;ROLE_ADMIN&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;hasAnyRole(&apos;ADMIN&apos;, &apos;USER&apos;)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否具有任一指定角色&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;hasAuthority(&apos;permission:query&apos;)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否具有指定权限&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;hasAnyAuthority(&apos;a&apos;, &apos;b&apos;)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否具有任一指定权限&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;isAuthenticated()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;当前用户是否已经认证&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

面试题：@PreAuthorize 的执行原理是什么？
&lt;div&gt;
&lt;p&gt;启用方法安全后，Spring Security 基于 Spring AOP 为受保护的 Spring Bean 创建代理。方法调用前，&lt;code&gt;AuthorizationManagerBeforeMethodInterceptor&lt;/code&gt; 读取 &lt;code&gt;@PreAuthorize&lt;/code&gt; 的 SpEL 表达式，并结合当前 &lt;code&gt;Authentication&lt;/code&gt; 进行授权判断。&lt;/p&gt;
&lt;p&gt;校验通过后才会调用目标方法；校验失败时会抛出 &lt;code&gt;AccessDeniedException&lt;/code&gt;。在 HTTP 请求链中，该异常通常被转换为 &lt;code&gt;403 Forbidden&lt;/code&gt; 响应。&lt;/p&gt;
&lt;/div&gt;

&lt;h2&gt;关键注意事项&lt;a href=&quot;#关键注意事项&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;认证成功不等于拥有所有权限，认证和授权必须分别配置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;401&lt;/code&gt; 表示未通过认证，&lt;code&gt;403&lt;/code&gt; 表示已经认证但权限不足。&lt;/li&gt;
&lt;li&gt;JWT 过滤器必须先验证签名和有效期，再创建已认证的 &lt;code&gt;Authentication&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;不要信任客户端直接提交的角色或权限。&lt;/li&gt;
&lt;li&gt;不要在 Token 或响应体中返回密码、密码摘要和密钥。&lt;/li&gt;
&lt;li&gt;CORS、CSRF、XSS 属于不同安全问题，不能相互替代。&lt;/li&gt;
&lt;li&gt;生产系统应使用 HTTPS，并配置合理的 Token 有效期、刷新和撤销机制。&lt;/li&gt;
&lt;li&gt;方法级授权适合保护 Service 层关键操作，不能只依赖前端按钮是否显示。&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:框架</category></item><item><title>JWT</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/framework/jwt</link><guid isPermaLink="false">learn/hyxy/framework/jwt</guid><description>JWT
JWT 概述
JWT（JSON Web Token）是一种紧凑、URL 安全的声明传输格式，常用于在不同系统之间传递身份与授权相关信息。
JWT 本身是一种令牌格式，并不等同于登录协议或单点登录方案。它可以作为认证、授权和单点登录流程中的一种令牌载体。

JWT</description><pubDate>Mon, 03 Aug 2026 01:56:11 GMT</pubDate><content:encoded>&lt;h1&gt;JWT&lt;a href=&quot;#jwt&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;JWT 概述&lt;a href=&quot;#jwt-概述&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;JWT（JSON Web Token）是一种紧凑、URL 安全的声明传输格式，常用于在不同系统之间传递身份与授权相关信息。&lt;/p&gt;
&lt;p&gt;JWT 本身是一种令牌格式，并不等同于登录协议或单点登录方案。它可以作为认证、授权和单点登录流程中的一种令牌载体。&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;JWT 是否保密取决于具体封装方式。常见的三段式 JWT 属于 JWS，仅提供签名或消息认证码保护，载荷内容仍可被读取；只有使用 JWE 时，载荷才会被加密。&lt;/p&gt;
&lt;/div&gt;
&lt;h2&gt;JWT 的常见应用场景&lt;a href=&quot;#jwt-的常见应用场景&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;身份认证&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;用户登录成功后，服务端签发 JWT。客户端在后续请求中携带该令牌，服务端通过校验签名、有效期、签发者和受众等信息判断令牌是否可信。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;访问授权&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;JWT 可以携带用户标识、角色、权限或作用域等声明。服务端完成令牌校验后，再根据这些声明判断当前用户是否可以访问目标资源。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;系统间信息交换&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;发送方可以对 JWT 进行签名，使接收方能够验证数据是否被篡改以及令牌是否由可信签发方生成。若业务还要求内容保密，应使用 JWE 或其他加密通道。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;单点登录&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在统一身份认证体系中，认证中心可以签发 JWT，各业务系统根据约定验证令牌。JWT 只是单点登录方案中的一个组成部分，完整方案还需要处理令牌签发、刷新、吊销和信任关系。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;JWT 的特点&lt;a href=&quot;#jwt-的特点&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;优点&lt;a href=&quot;#优点&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;格式紧凑&lt;/strong&gt;：适合放在 HTTP 请求头中传输。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;跨语言&lt;/strong&gt;：JWT 是标准化格式，各主流语言均有相应实现。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;便于分布式验证&lt;/strong&gt;：资源服务器可以在本地验证签名，减少对集中式会话存储的依赖。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;支持声明扩展&lt;/strong&gt;：除标准声明外，还可以添加业务自定义声明。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;局限&lt;a href=&quot;#局限&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;已签发令牌不易立即撤销&lt;/strong&gt;：通常需要缩短有效期、维护黑名单或使用令牌版本号等机制。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;载荷可能泄露信息&lt;/strong&gt;：JWS 的载荷只是 Base64URL 编码，并未加密。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;令牌体积可能较大&lt;/strong&gt;：声明过多时，每次请求都会增加网络开销。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;权限可能过期&lt;/strong&gt;：若把权限直接写入长时效令牌，数据库权限变更不会立即反映到旧令牌中。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;JWT 的结构&lt;a href=&quot;#jwt-的结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;常见的签名 JWT 由三部分组成，并使用英文句点连接：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Header.Payload.Signature&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260803100037851.png&quot; alt=&quot;image-001&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-001&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;Header&lt;a href=&quot;#header&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Header 是一个 JSON 对象，通常包含以下字段：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;typ&lt;/code&gt;：令牌类型，通常为 &lt;code&gt;JWT&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alg&lt;/code&gt;：签名或消息认证码算法，例如 &lt;code&gt;HS256&lt;/code&gt;、&lt;code&gt;RS256&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;typ&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;JWT&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;alg&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;HS256&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Header 会经过 Base64URL 编码，形成令牌的第一部分。&lt;/p&gt;
&lt;h3&gt;Payload&lt;a href=&quot;#payload&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Payload 用于存放声明（Claim）。JWT 规范定义了七个注册声明名称，这些字段均为可选字段。&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;声明&lt;/th&gt;&lt;th&gt;英文名称&lt;/th&gt;&lt;th&gt;作用&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;iss&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Issuer&lt;/td&gt;&lt;td&gt;标识令牌签发者&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;sub&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Subject&lt;/td&gt;&lt;td&gt;标识令牌主题，通常代表用户或主体&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;aud&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Audience&lt;/td&gt;&lt;td&gt;标识令牌预期接收方&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;exp&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Expiration Time&lt;/td&gt;&lt;td&gt;标识令牌过期时间&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;nbf&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Not Before&lt;/td&gt;&lt;td&gt;标识令牌在何时之前不可用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;iat&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Issued At&lt;/td&gt;&lt;td&gt;标识令牌签发时间&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;jti&lt;/code&gt;&lt;/td&gt;&lt;td&gt;JWT ID&lt;/td&gt;&lt;td&gt;标识令牌的唯一编号&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;除注册声明外，还可以添加业务自定义声明：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;sub&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;1234567890&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;name&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;John Doe&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;admin&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;
&lt;p&gt;不要在未加密的 JWT Payload 中存放密码、银行卡号、身份证号、密钥等敏感信息。任何获得令牌的人都可以解码并读取 Header 和 Payload。&lt;/p&gt;
&lt;/div&gt;
&lt;h3&gt;Signature&lt;a href=&quot;#signature&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Signature 用于校验 Header 和 Payload 是否被篡改，并验证令牌是否由持有相应密钥的一方签发。&lt;/p&gt;
&lt;p&gt;以 &lt;code&gt;HS256&lt;/code&gt; 为例，签名计算过程可以表示为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;HMACSHA256(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    base64UrlEncode(header) + &quot;.&quot; + base64UrlEncode(payload),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    secret&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用 HMAC 时，签发方与验证方共享同一个密钥；使用 RSA 或 ECDSA 时，签发方使用私钥签名，验证方使用公钥验签。&lt;/p&gt;
&lt;p&gt;签名只能保证完整性和来源可信度，不能隐藏 Payload 内容。&lt;/p&gt;
&lt;h3&gt;Base64URL&lt;a href=&quot;#base64url&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Base64URL 是适合 URL 和 HTTP 头部传输的 Base64 变体。&lt;/p&gt;
&lt;p&gt;与普通 Base64 相比，它主要进行以下处理：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;将 &lt;code&gt;+&lt;/code&gt; 替换为 &lt;code&gt;-&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;将 &lt;code&gt;/&lt;/code&gt; 替换为 &lt;code&gt;_&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;省略末尾的 &lt;code&gt;=&lt;/code&gt; 填充字符。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Base64URL 是编码方式，不是加密算法。&lt;/p&gt;
&lt;h2&gt;使用 JJWT 封装工具类&lt;a href=&quot;#使用-jjwt-封装工具类&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;下面示例基于 JJWT &lt;code&gt;0.12.x&lt;/code&gt;。配置项中的密钥使用 Base64 编码，并且解码后至少应满足所选 HMAC 算法的密钥长度要求。&lt;/p&gt;
&lt;h3&gt;配置示例&lt;a href=&quot;#配置示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;jwt&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  secret&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;${JWT_SECRET}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  expire-ms&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;86400000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;JWT_SECRET&lt;/code&gt; 不应直接提交到代码仓库，可通过环境变量或密钥管理服务注入。&lt;/p&gt;
&lt;h3&gt;JWT 工具类&lt;a href=&quot;#jwt-工具类&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.jsonwebtoken.Claims;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.jsonwebtoken.Jwts;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.jsonwebtoken.io.Decoders;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.jsonwebtoken.security.Keys;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.beans.factory.annotation.Value;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.stereotype.Component;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; javax.crypto.SecretKey;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.Date;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; JwtUtil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; SecretKey key;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; long&lt;/span&gt;&lt;span&gt; expireMs;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; JwtUtil&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;${jwt.secret}&quot;&lt;/span&gt;&lt;span&gt;) String &lt;/span&gt;&lt;span&gt;secret&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;${jwt.expire-ms}&quot;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; expireMs&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        byte&lt;/span&gt;&lt;span&gt;[] keyBytes &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Decoders.BASE64.&lt;/span&gt;&lt;span&gt;decode&lt;/span&gt;&lt;span&gt;(secret);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.key &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Keys.&lt;/span&gt;&lt;span&gt;hmacShaKeyFor&lt;/span&gt;&lt;span&gt;(keyBytes);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.expireMs &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; expireMs;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;createToken&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Long &lt;/span&gt;&lt;span&gt;userId&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            String &lt;/span&gt;&lt;span&gt;username&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Long &lt;/span&gt;&lt;span&gt;roleId&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;permissions&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Date now &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Date&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Date expiration &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Date&lt;/span&gt;&lt;span&gt;(now.&lt;/span&gt;&lt;span&gt;getTime&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; expireMs);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; Jwts.&lt;/span&gt;&lt;span&gt;builder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;subject&lt;/span&gt;&lt;span&gt;(username)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;claim&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;userId&quot;&lt;/span&gt;&lt;span&gt;, userId)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;claim&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;roleId&quot;&lt;/span&gt;&lt;span&gt;, roleId)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;claim&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;permissions&quot;&lt;/span&gt;&lt;span&gt;, permissions)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;issuedAt&lt;/span&gt;&lt;span&gt;(now)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;expiration&lt;/span&gt;&lt;span&gt;(expiration)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;signWith&lt;/span&gt;&lt;span&gt;(key)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;compact&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Claims &lt;/span&gt;&lt;span&gt;parseToken&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;token&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; Jwts.&lt;/span&gt;&lt;span&gt;parser&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;verifyWith&lt;/span&gt;&lt;span&gt;(key)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;parseSignedClaims&lt;/span&gt;&lt;span&gt;(token)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;getPayload&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; isExpired&lt;/span&gt;&lt;span&gt;(Claims &lt;/span&gt;&lt;span&gt;claims&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Date expiration &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; claims.&lt;/span&gt;&lt;span&gt;getExpiration&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; expiration &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; expiration.&lt;/span&gt;&lt;span&gt;before&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; Date&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;signWith(key)&lt;/code&gt; 会根据密钥类型和长度选择兼容的签名算法。若系统要求固定算法，应在签发和验证两端统一配置，并限制只接受预期算法。&lt;/p&gt;
&lt;h2&gt;Claims 对象&lt;a href=&quot;#claims-对象&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Claims&lt;/code&gt; 表示 JWT 中的声明集合。它继承了 &lt;code&gt;Map&amp;lt;String, Object&amp;gt;&lt;/code&gt; 的键值存取能力，同时提供了读取标准声明的专用方法。&lt;/p&gt;
&lt;p&gt;常用方法如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;String subject &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; claims.&lt;/span&gt;&lt;span&gt;getSubject&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Date issuedAt &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; claims.&lt;/span&gt;&lt;span&gt;getIssuedAt&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Date expiration &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; claims.&lt;/span&gt;&lt;span&gt;getExpiration&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;String issuer &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; claims.&lt;/span&gt;&lt;span&gt;getIssuer&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;读取自定义声明时，可以指定目标类型：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Long userId &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; claims.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;userId&quot;&lt;/span&gt;&lt;span&gt;, Long.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Long roleId &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; claims.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;roleId&quot;&lt;/span&gt;&lt;span&gt;, Long.class);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对于泛型集合，由于 Java 类型擦除，直接读取时通常只能得到原始 &lt;code&gt;List&lt;/code&gt;。可以在业务层逐项转换，或使用自定义反序列化方案。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;SuppressWarnings&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;unchecked&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; permissions &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; claims.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;permissions&quot;&lt;/span&gt;&lt;span&gt;, List.class);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;测试令牌的创建与解析&lt;a href=&quot;#测试令牌的创建与解析&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;下面的测试在同一个测试方法中创建并解析令牌，避免使用已经过期或被换行破坏的硬编码令牌。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.jsonwebtoken.Claims;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.junit.jupiter.api.Test;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.beans.factory.annotation.Autowired;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.boot.test.context.SpringBootTest;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; org.junit.jupiter.api.Assertions.assertEquals;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; org.junit.jupiter.api.Assertions.assertFalse;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;SpringBootTest&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; JwtUtilTests&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Autowired&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; JwtUtil jwtUtil;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    void&lt;/span&gt;&lt;span&gt; shouldCreateAndParseToken&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; permissions &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; List.&lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;permission:query&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;permission:insert&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;permission:update&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;permission:delete&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;permission:check&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String token &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; jwtUtil.&lt;/span&gt;&lt;span&gt;createToken&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;130L&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;tom&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3L&lt;/span&gt;&lt;span&gt;, permissions);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Claims claims &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; jwtUtil.&lt;/span&gt;&lt;span&gt;parseToken&lt;/span&gt;&lt;span&gt;(token);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        assertEquals&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;tom&quot;&lt;/span&gt;&lt;span&gt;, claims.&lt;/span&gt;&lt;span&gt;getSubject&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        assertEquals&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;130L&lt;/span&gt;&lt;span&gt;, claims.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;userId&quot;&lt;/span&gt;&lt;span&gt;, Long.class));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        assertEquals&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;3L&lt;/span&gt;&lt;span&gt;, claims.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;roleId&quot;&lt;/span&gt;&lt;span&gt;, Long.class));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        assertFalse&lt;/span&gt;&lt;span&gt;(jwtUtil.&lt;/span&gt;&lt;span&gt;isExpired&lt;/span&gt;&lt;span&gt;(claims));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        @&lt;/span&gt;&lt;span&gt;SuppressWarnings&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;unchecked&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; parsedPermissions &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; claims.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;permissions&quot;&lt;/span&gt;&lt;span&gt;, List.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        assertEquals&lt;/span&gt;&lt;span&gt;(permissions, parsedPermissions);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;使用注意事项&lt;a href=&quot;#使用注意事项&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;服务端必须验证签名，不能只解码 Payload。&lt;/li&gt;
&lt;li&gt;应校验 &lt;code&gt;exp&lt;/code&gt;，并根据业务需要校验 &lt;code&gt;iss&lt;/code&gt;、&lt;code&gt;aud&lt;/code&gt;、&lt;code&gt;nbf&lt;/code&gt; 等声明。&lt;/li&gt;
&lt;li&gt;不要接受客户端自行指定的任意算法，应限制允许的算法和令牌类型。&lt;/li&gt;
&lt;li&gt;HMAC 密钥必须足够长且随机，不能使用简单口令代替密钥。&lt;/li&gt;
&lt;li&gt;访问令牌应设置较短有效期；需要长期登录时，应配合刷新令牌机制。&lt;/li&gt;
&lt;li&gt;全程使用 HTTPS，避免令牌在传输过程中被窃取。&lt;/li&gt;
&lt;li&gt;客户端存储方案应根据威胁模型选择，并重点防范 XSS、CSRF 和令牌泄露。&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:框架</category></item><item><title>Coze 平台架构、典型应用案例及优势与适用场景</title><link>https://blog.hoshiumi.xyz/post/lab/coze-ping-tai-jia-gou-dian-xing-ying-yong-an-li-ji-you-shi-yu-gua-yong-chang-jing</link><guid isPermaLink="false">lab/coze-ping-tai-jia-gou-dian-xing-ying-yong-an-li-ji-you-shi-yu-gua-yong-chang-jing</guid><description>Coze 平台架构、典型应用案例及优势与适用场景
Coze 平台架构
两种平台形态
Coze 官网版（云端版）
Coze 官网版属于官方托管的在线服务。用户通过浏览器访问平台，直接使用官方提供的模型、应用能力、在线运行环境和相关服务，不需要自行安装程序或维护服务器。
官网版的主要特点包括：</description><pubDate>Sat, 01 Aug 2026 11:59:38 GMT</pubDate><content:encoded>&lt;h1&gt;Coze 平台架构、典型应用案例及优势与适用场景&lt;a href=&quot;#coze-平台架构典型应用案例及优势与适用场景&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Coze 平台架构&lt;a href=&quot;#coze-平台架构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;两种平台形态&lt;a href=&quot;#两种平台形态&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;Coze 官网版（云端版）&lt;a href=&quot;#coze-官网版云端版&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Coze 官网版属于官方托管的在线服务。用户通过浏览器访问平台，直接使用官方提供的模型、应用能力、在线运行环境和相关服务，不需要自行安装程序或维护服务器。&lt;/p&gt;
&lt;p&gt;官网版的主要特点包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;注册后即可在线使用；&lt;/li&gt;
&lt;li&gt;平台环境由官方统一维护；&lt;/li&gt;
&lt;li&gt;适合快速体验、课程教学和原型验证；&lt;/li&gt;
&lt;li&gt;可以直接使用官网提供的功能与生态资源；&lt;/li&gt;
&lt;li&gt;无需自行处理系统升级、基础设施和日常运维；&lt;/li&gt;
&lt;li&gt;实际可用功能、资源额度和发布能力以官网当前版本为准。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Coze 官网当前将自身描述为面向职场任务的 AI 产品，并提供 AI 应用、工作产物生成、长期任务以及相关开发能力。&lt;/p&gt;
&lt;h4&gt;Coze Studio（开源版）&lt;a href=&quot;#coze-studio开源版&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Coze Studio 是 Coze 平台核心引擎的开源版本。开发者可以将其部署到本地计算机、实验室服务器或企业内网中，构建自主可控的 AI Agent 开发平台。&lt;/p&gt;
&lt;p&gt;开源版的主要特点包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;支持私有化部署；&lt;/li&gt;
&lt;li&gt;数据和运行环境可由部署方管理；&lt;/li&gt;
&lt;li&gt;可以接入自有模型和业务服务；&lt;/li&gt;
&lt;li&gt;支持根据源代码进行功能修改；&lt;/li&gt;
&lt;li&gt;适合教学研究、企业内网和二次开发；&lt;/li&gt;
&lt;li&gt;需要具备一定的部署、配置和运维能力。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Coze Studio 官方说明其提供 Prompt、RAG、Plugin 和 Workflow 等 AI Agent 开发核心技术，并采用可视化方式支持智能体、应用和工作流的开发、调试与部署。&lt;/p&gt;
&lt;h4&gt;官网版与开源版对比&lt;a href=&quot;#官网版与开源版对比&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;






































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;对比维度&lt;/th&gt;&lt;th&gt;Coze 官网版（云端版）&lt;/th&gt;&lt;th&gt;Coze Studio（开源版）&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;使用方式&lt;/td&gt;&lt;td&gt;浏览器在线使用&lt;/td&gt;&lt;td&gt;本地或服务器部署&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;环境维护&lt;/td&gt;&lt;td&gt;官方统一维护&lt;/td&gt;&lt;td&gt;用户自行维护&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;上手难度&lt;/td&gt;&lt;td&gt;较低，注册后即可使用&lt;/td&gt;&lt;td&gt;较高，需要部署和配置&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;数据存放&lt;/td&gt;&lt;td&gt;由云端平台按服务规则处理&lt;/td&gt;&lt;td&gt;可由部署方在自有环境中管理&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;功能获取&lt;/td&gt;&lt;td&gt;直接使用官网当前提供的功能&lt;/td&gt;&lt;td&gt;使用开源功能，并可自行扩展&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;模型配置&lt;/td&gt;&lt;td&gt;以官网支持范围和平台规则为准&lt;/td&gt;&lt;td&gt;可根据部署环境配置支持的模型&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;插件与服务&lt;/td&gt;&lt;td&gt;可使用官网生态和在线服务&lt;/td&gt;&lt;td&gt;需配置开源插件或接入自有 API&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;二次开发&lt;/td&gt;&lt;td&gt;主要通过平台配置和开放接口&lt;/td&gt;&lt;td&gt;可修改源代码并深度定制&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;运维成本&lt;/td&gt;&lt;td&gt;较低&lt;/td&gt;&lt;td&gt;较高&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;适用对象&lt;/td&gt;&lt;td&gt;初学者、个人用户、快速验证团队&lt;/td&gt;&lt;td&gt;技术团队、实验室、企业私有化项目&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;主要优势&lt;/td&gt;&lt;td&gt;开箱即用、使用便捷&lt;/td&gt;&lt;td&gt;自主可控、便于定制&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;主要限制&lt;/td&gt;&lt;td&gt;受平台功能、额度和服务规则影响&lt;/td&gt;&lt;td&gt;需要自行解决部署、资源和运维问题&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;两种形态具有相近的 AI Agent 开发理念，但在具体功能、官方生态、资源额度、发布渠道和运行维护方式上可能存在差异，使用时应以对应版本的最新官方说明为准。&lt;/p&gt;
&lt;h3&gt;平台能力架构&lt;a href=&quot;#平台能力架构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;从 AI 应用构建过程来看，Coze 可以划分为五个相互协作的能力层。&lt;/p&gt;
&lt;pre&gt;flowchart TB
    A[用户与业务系统]

    B[应用与交互层&amp;lt;br/&amp;gt;智能体 Agent / AI 应用 App / 对话界面 / API]
    C[智能与编排层&amp;lt;br/&amp;gt;大语言模型 / 提示词 / 工作流]
    D[能力扩展层&amp;lt;br/&amp;gt;插件 / 工具 / 第三方 API]
    E[知识与数据层&amp;lt;br/&amp;gt;知识库 / 数据库 / 长期记忆]
    F[开发与发布支撑&amp;lt;br/&amp;gt;可视化工作台 / 调试 / 发布 / 管理]

    A --&amp;gt; B
    B --&amp;gt; C
    C --&amp;gt; D
    C --&amp;gt; E
    F -.支撑.-&amp;gt; B
    F -.支撑.-&amp;gt; C
    F -.支撑.-&amp;gt; D
    F -.支撑.-&amp;gt; E&lt;/pre&gt;
&lt;h4&gt;应用与交互层&lt;a href=&quot;#应用与交互层&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;应用与交互层直接面向最终用户，负责承接用户需求并展示 AI 处理结果。&lt;/p&gt;
&lt;p&gt;该层主要包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;智能体 Agent&lt;/strong&gt;：以自然语言对话为主要交互方式，可以理解任务、选择工具并返回结果；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI 应用 App&lt;/strong&gt;：围绕特定业务需求构建，通常具有明确的输入、输出和可视化界面；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;对话界面&lt;/strong&gt;：用户与智能体进行问答和任务交互的入口；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;API 与 SDK&lt;/strong&gt;：用于将 Coze 的智能体或工作流接入网站、管理系统和其他业务软件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;智能体更适合开放式对话和动态任务，AI 应用更适合业务目标明确、流程相对固定的功能场景。&lt;/p&gt;
&lt;h4&gt;智能与编排层&lt;a href=&quot;#智能与编排层&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;智能与编排层是平台的核心，负责理解用户意图、组织业务逻辑和生成最终结果。&lt;/p&gt;
&lt;p&gt;该层主要包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;大语言模型；&lt;/li&gt;
&lt;li&gt;提示词；&lt;/li&gt;
&lt;li&gt;智能体决策逻辑；&lt;/li&gt;
&lt;li&gt;工作流。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;大语言模型负责理解、推理和生成；提示词规定模型的角色与行为；工作流负责将复杂任务拆分为多个步骤，并按照确定的逻辑依次执行。&lt;/p&gt;
&lt;h4&gt;能力扩展层&lt;a href=&quot;#能力扩展层&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;能力扩展层通过插件和工具连接外部世界，使大模型从“只能生成内容”扩展为“能够获取信息和执行操作”。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;调用搜索工具获取实时新闻；&lt;/li&gt;
&lt;li&gt;调用天气服务查询天气；&lt;/li&gt;
&lt;li&gt;调用地图服务规划路线；&lt;/li&gt;
&lt;li&gt;调用图像生成服务制作图片；&lt;/li&gt;
&lt;li&gt;调用企业 API 查询订单或客户信息；&lt;/li&gt;
&lt;li&gt;调用邮件、日程等服务完成办公任务。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;知识与数据层&lt;a href=&quot;#知识与数据层&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;知识与数据层为智能体提供专业知识、业务数据和长期状态。&lt;/p&gt;
&lt;p&gt;主要包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;知识库&lt;/strong&gt;：保存企业文档、产品手册、课程资料和行业报告，为智能体提供检索增强生成能力；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;数据库&lt;/strong&gt;：保存结构化业务数据；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;长期记忆&lt;/strong&gt;：记录用户偏好、历史任务和交互信息，使智能体能够在后续会话中继续使用这些信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;开发与发布支撑&lt;a href=&quot;#开发与发布支撑&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;开发与发布能力贯穿整个应用构建过程，主要包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可视化工作台；&lt;/li&gt;
&lt;li&gt;拖拽式工作流画布；&lt;/li&gt;
&lt;li&gt;实时预览和调试；&lt;/li&gt;
&lt;li&gt;应用配置和资源管理；&lt;/li&gt;
&lt;li&gt;智能体与应用发布；&lt;/li&gt;
&lt;li&gt;API 和 SDK 集成。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;该层降低了开发门槛，使非专业开发人员也可以参与 AI 应用的设计和迭代。&lt;/p&gt;
&lt;h2&gt;Coze 平台核心组件&lt;a href=&quot;#coze-平台核心组件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;大语言模型&lt;a href=&quot;#大语言模型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;大语言模型是 Coze 平台的智能核心，主要负责：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;理解自然语言；&lt;/li&gt;
&lt;li&gt;识别用户意图；&lt;/li&gt;
&lt;li&gt;生成文本内容；&lt;/li&gt;
&lt;li&gt;进行逻辑推理；&lt;/li&gt;
&lt;li&gt;判断是否调用插件或工作流；&lt;/li&gt;
&lt;li&gt;整合知识库和工具返回的结果。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;模型能力会直接影响智能体的理解准确率、回答质量和工具调用稳定性。&lt;/p&gt;
&lt;h3&gt;智能体 Agent&lt;a href=&quot;#智能体-agent&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;智能体是能够通过自然语言与用户交互，并根据任务需要调用知识库、插件或工作流的 AI 项目。&lt;/p&gt;
&lt;p&gt;一个完整的智能体通常由以下内容组成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;角色和身份；&lt;/li&gt;
&lt;li&gt;系统提示词；&lt;/li&gt;
&lt;li&gt;大语言模型；&lt;/li&gt;
&lt;li&gt;对话上下文；&lt;/li&gt;
&lt;li&gt;知识库；&lt;/li&gt;
&lt;li&gt;插件和工具；&lt;/li&gt;
&lt;li&gt;工作流；&lt;/li&gt;
&lt;li&gt;数据库与记忆；&lt;/li&gt;
&lt;li&gt;开场白和推荐问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;智能体不是简单的问答机器人。它可以根据用户目标选择不同能力，完成“理解—决策—执行—反馈”的任务闭环。&lt;/p&gt;
&lt;h3&gt;AI 应用 App&lt;a href=&quot;#ai-应用-app&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;AI 应用是围绕特定业务需求构建的独立项目，具有较明确的输入、输出和处理逻辑。&lt;/p&gt;
&lt;p&gt;典型 AI 应用包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI 搜索；&lt;/li&gt;
&lt;li&gt;翻译工具；&lt;/li&gt;
&lt;li&gt;报告生成器；&lt;/li&gt;
&lt;li&gt;数据格式转换工具；&lt;/li&gt;
&lt;li&gt;饮食记录工具；&lt;/li&gt;
&lt;li&gt;内容审核工具。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;与智能体相比，AI 应用的功能边界通常更加明确，适合提供标准化服务。&lt;/p&gt;
&lt;h3&gt;提示词 Prompt&lt;a href=&quot;#提示词-prompt&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;提示词用于定义智能体的身份、任务目标、工作步骤、回复风格和行为边界，是控制智能体表现的重要组件。&lt;/p&gt;
&lt;p&gt;一份结构清晰的提示词通常包括：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;角色定位&lt;/strong&gt;：智能体是谁；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;任务目标&lt;/strong&gt;：需要完成什么；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;工作流程&lt;/strong&gt;：按照什么步骤处理；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可用资源&lt;/strong&gt;：可以调用哪些知识库、插件和工作流；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;输出规范&lt;/strong&gt;：语言、格式、长度和结构要求；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;行为约束&lt;/strong&gt;：禁止事项和异常处理方式。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;提示词能够约束模型行为，但不能替代程序权限控制、内容审核和安全校验。&lt;/p&gt;
&lt;h3&gt;工作流 Workflow&lt;a href=&quot;#工作流-workflow&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;工作流用于将复杂任务拆分为多个可执行节点，并通过节点之间的连接组织数据流和执行顺序。&lt;/p&gt;
&lt;p&gt;常见节点包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;大语言模型节点；&lt;/li&gt;
&lt;li&gt;插件节点；&lt;/li&gt;
&lt;li&gt;知识库检索节点；&lt;/li&gt;
&lt;li&gt;代码节点；&lt;/li&gt;
&lt;li&gt;条件判断节点；&lt;/li&gt;
&lt;li&gt;循环节点；&lt;/li&gt;
&lt;li&gt;数据处理节点；&lt;/li&gt;
&lt;li&gt;输入和输出节点。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;工作流适合执行流程明确、步骤较多、稳定性要求较高的任务，例如行业报告生成、订单处理、数据分析和内容审核。&lt;/p&gt;
&lt;h3&gt;插件与工具&lt;a href=&quot;#插件与工具&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;工具是完成某一具体操作的能力，例如查询天气；插件则是一个或多个相关工具组成的能力集合。&lt;/p&gt;
&lt;p&gt;插件的主要作用是：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;获取大模型知识范围之外的实时信息；&lt;/li&gt;
&lt;li&gt;调用第三方服务；&lt;/li&gt;
&lt;li&gt;连接企业内部业务系统；&lt;/li&gt;
&lt;li&gt;执行查询、计算、生成和通知等操作。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;官方说明指出，插件工具能够扩展大语言模型的能力，使其连接外部世界。&lt;/p&gt;
&lt;h3&gt;知识库与 RAG&lt;a href=&quot;#知识库与-rag&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;知识库用于保存企业内部资料、课程文件、产品手册、行业文档和网页内容。&lt;/p&gt;
&lt;p&gt;当用户提出问题时，系统可以先从知识库中检索相关内容，再将检索结果交给大语言模型生成回答。这种“先检索、再生成”的方式属于 RAG，即检索增强生成。&lt;/p&gt;
&lt;p&gt;知识库的主要价值包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;补充模型不了解的企业私有知识；&lt;/li&gt;
&lt;li&gt;提高专业领域回答的准确性；&lt;/li&gt;
&lt;li&gt;减少无依据回答；&lt;/li&gt;
&lt;li&gt;让智能体依据指定资料回答问题；&lt;/li&gt;
&lt;li&gt;降低用户查找大量文档的时间成本。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;RAG 能够降低模型幻觉，但不能完全消除错误，重要内容仍需要依据引用和人工复核。&lt;/p&gt;
&lt;h3&gt;数据库与长期记忆&lt;a href=&quot;#数据库与长期记忆&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;数据库用于保存结构化信息，长期记忆用于保存用户偏好、历史交互和任务状态。&lt;/p&gt;
&lt;p&gt;例如，阅读助手可以记录：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;书名；&lt;/li&gt;
&lt;li&gt;阅读页码；&lt;/li&gt;
&lt;li&gt;阅读时间；&lt;/li&gt;
&lt;li&gt;用户笔记；&lt;/li&gt;
&lt;li&gt;兴趣偏好。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当用户再次对话时，智能体可以查询历史数据并继续提供服务，从而由一次性问答工具转变为长期个人助手。&lt;/p&gt;
&lt;h3&gt;调试与发布&lt;a href=&quot;#调试与发布&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Coze 提供可视化预览和调试能力。开发者可以在发布前测试：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;提示词是否清晰；&lt;/li&gt;
&lt;li&gt;回答风格是否符合要求；&lt;/li&gt;
&lt;li&gt;插件能否正常调用；&lt;/li&gt;
&lt;li&gt;工作流是否按照预期执行；&lt;/li&gt;
&lt;li&gt;知识库检索结果是否准确；&lt;/li&gt;
&lt;li&gt;异常情况是否得到合理处理。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;测试完成后，可将智能体或应用发布并供用户使用，也可以通过 API 或 SDK 接入现有系统。&lt;/p&gt;
&lt;h3&gt;核心组件协作关系&lt;a href=&quot;#核心组件协作关系&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;核心组件&lt;/th&gt;&lt;th&gt;主要作用&lt;/th&gt;&lt;th&gt;典型协作对象&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;大语言模型&lt;/td&gt;&lt;td&gt;理解、推理、生成和决策&lt;/td&gt;&lt;td&gt;提示词、智能体、工作流&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;智能体&lt;/td&gt;&lt;td&gt;接收用户任务并组织执行&lt;/td&gt;&lt;td&gt;模型、知识库、插件、工作流、记忆&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;AI 应用&lt;/td&gt;&lt;td&gt;封装特定业务功能&lt;/td&gt;&lt;td&gt;模型、工作流、API&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;提示词&lt;/td&gt;&lt;td&gt;规定角色、任务和输出边界&lt;/td&gt;&lt;td&gt;模型、智能体&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;工作流&lt;/td&gt;&lt;td&gt;编排多步骤业务流程&lt;/td&gt;&lt;td&gt;模型、插件、知识库、代码&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;插件与工具&lt;/td&gt;&lt;td&gt;获取实时信息或执行外部操作&lt;/td&gt;&lt;td&gt;智能体、工作流、第三方系统&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;知识库&lt;/td&gt;&lt;td&gt;提供私有知识和检索依据&lt;/td&gt;&lt;td&gt;智能体、模型&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;数据库与记忆&lt;/td&gt;&lt;td&gt;保存业务数据和长期状态&lt;/td&gt;&lt;td&gt;智能体、用户、应用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;API 与 SDK&lt;/td&gt;&lt;td&gt;将平台能力接入其他系统&lt;/td&gt;&lt;td&gt;网站、企业系统、移动应用&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Coze 平台典型应用案例&lt;a href=&quot;#coze-平台典型应用案例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;夸夸机器人&lt;a href=&quot;#夸夸机器人&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;业务需求&lt;a href=&quot;#业务需求&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;通过对话识别用户表达中的积极信息，并以幽默、真诚和正向的语言进行赞美。&lt;/p&gt;
&lt;h4&gt;使用组件&lt;a href=&quot;#使用组件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;智能体；&lt;/li&gt;
&lt;li&gt;大语言模型；&lt;/li&gt;
&lt;li&gt;系统提示词；&lt;/li&gt;
&lt;li&gt;开场白和推荐问题；&lt;/li&gt;
&lt;li&gt;可选搜索插件。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;实现效果&lt;a href=&quot;#实现效果&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;通过提示词设定“夸夸大师”的角色、语言风格和回答边界，使机器人始终提供积极反馈。该案例适合用于展示智能体创建、提示词编写、调试和发布等基础能力。&lt;/p&gt;
&lt;h3&gt;智能客服&lt;a href=&quot;#智能客服&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;业务需求&lt;a href=&quot;#业务需求-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;企业需要持续处理大量重复咨询，例如产品功能、售后规则、订单状态和常见故障。&lt;/p&gt;
&lt;h4&gt;使用组件&lt;a href=&quot;#使用组件-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;智能体；&lt;/li&gt;
&lt;li&gt;企业知识库；&lt;/li&gt;
&lt;li&gt;搜索或订单查询插件；&lt;/li&gt;
&lt;li&gt;工作流；&lt;/li&gt;
&lt;li&gt;API 与 SDK。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;实现效果&lt;a href=&quot;#实现效果-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;智能客服可以全天候回答常见问题。当问题涉及企业制度或产品参数时，从知识库检索答案；涉及订单状态时，调用业务系统 API；遇到复杂问题时，可通过工作流转交人工客服。&lt;/p&gt;
&lt;h3&gt;企业知识问答助手&lt;a href=&quot;#企业知识问答助手&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;业务需求&lt;a href=&quot;#业务需求-2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;企业员工需要从员工手册、产品文档、项目资料和规章制度中快速查找信息。&lt;/p&gt;
&lt;h4&gt;使用组件&lt;a href=&quot;#使用组件-2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;智能体；&lt;/li&gt;
&lt;li&gt;知识库；&lt;/li&gt;
&lt;li&gt;RAG；&lt;/li&gt;
&lt;li&gt;权限控制；&lt;/li&gt;
&lt;li&gt;对话界面。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;实现效果&lt;a href=&quot;#实现效果-2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;企业将内部文档导入知识库，员工可以直接提问“差旅费报销标准是什么”或“产品 A 的核心参数有哪些”。智能体检索相关资料后生成答案，减少人工查找文件和重复咨询的成本。&lt;/p&gt;
&lt;h3&gt;AI 新闻播音员&lt;a href=&quot;#ai-新闻播音员&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;业务需求&lt;a href=&quot;#业务需求-3&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;用户希望定期获取特定领域的最新新闻，并将多个信息源整理成简洁摘要。&lt;/p&gt;
&lt;h4&gt;使用组件&lt;a href=&quot;#使用组件-3&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;智能体；&lt;/li&gt;
&lt;li&gt;新闻搜索插件；&lt;/li&gt;
&lt;li&gt;工作流；&lt;/li&gt;
&lt;li&gt;大语言模型；&lt;/li&gt;
&lt;li&gt;定时任务或外部触发能力。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;实现效果&lt;a href=&quot;#实现效果-3&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;系统调用新闻搜索插件获取实时资讯，通过工作流进行筛选、去重和分类，再由大语言模型生成播报稿。该案例体现了插件、工作流和文本生成能力的结合。&lt;/p&gt;
&lt;h3&gt;行业研究报告生成&lt;a href=&quot;#行业研究报告生成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;业务需求&lt;a href=&quot;#业务需求-4&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;传统行业研究报告需要经历资料搜索、数据整理、大纲设计、内容撰写和格式检查等多个步骤，耗时较长。&lt;/p&gt;
&lt;h4&gt;使用组件&lt;a href=&quot;#使用组件-4&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;工作流；&lt;/li&gt;
&lt;li&gt;搜索插件；&lt;/li&gt;
&lt;li&gt;知识库；&lt;/li&gt;
&lt;li&gt;大语言模型；&lt;/li&gt;
&lt;li&gt;条件判断和代码节点；&lt;/li&gt;
&lt;li&gt;文档输出工具。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;实现效果&lt;a href=&quot;#实现效果-4&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;工作流可将报告生成划分为：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;接收研究主题；&lt;/li&gt;
&lt;li&gt;搜集公开资料；&lt;/li&gt;
&lt;li&gt;检索内部知识库；&lt;/li&gt;
&lt;li&gt;生成报告大纲；&lt;/li&gt;
&lt;li&gt;分章节撰写；&lt;/li&gt;
&lt;li&gt;检查逻辑和格式；&lt;/li&gt;
&lt;li&gt;输出最终报告。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;该案例适合展示 Coze 对多步骤、复杂知识工作的自动化能力。&lt;/p&gt;
&lt;h3&gt;汽车品牌智能销售系统&lt;a href=&quot;#汽车品牌智能销售系统&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;业务需求&lt;a href=&quot;#业务需求-5&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;汽车销售人员需要根据用户浏览行为、咨询内容和车型偏好判断购买意向，并提供个性化推荐。&lt;/p&gt;
&lt;h4&gt;使用组件&lt;a href=&quot;#使用组件-5&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;智能体；&lt;/li&gt;
&lt;li&gt;客户数据库；&lt;/li&gt;
&lt;li&gt;企业知识库；&lt;/li&gt;
&lt;li&gt;推荐工作流；&lt;/li&gt;
&lt;li&gt;CRM 系统插件。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;实现效果&lt;a href=&quot;#实现效果-5&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;系统分析客户咨询关键词、车型偏好和历史行为，形成用户画像，并向销售人员提供推荐车型、沟通重点和参考话术。&lt;/p&gt;
&lt;h3&gt;电商订单处理自动化&lt;a href=&quot;#电商订单处理自动化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;业务需求&lt;a href=&quot;#业务需求-6&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;非标准化订单常以自然语言描述产品规格，人工整理容易出现遗漏和录入错误。&lt;/p&gt;
&lt;h4&gt;使用组件&lt;a href=&quot;#使用组件-6&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;工作流；&lt;/li&gt;
&lt;li&gt;大语言模型；&lt;/li&gt;
&lt;li&gt;条件判断；&lt;/li&gt;
&lt;li&gt;数据处理节点；&lt;/li&gt;
&lt;li&gt;订单系统和供应链插件。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;实现效果&lt;a href=&quot;#实现效果-6&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;系统自动读取订单描述，提取材质、尺寸、数量和定制要求，将非结构化文本转化为结构化订单或 BOM 清单，再传递给供应链系统，从而减少人工录入并提高订单处理效率。&lt;/p&gt;
&lt;h3&gt;个性化阅读助手&lt;a href=&quot;#个性化阅读助手&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;业务需求&lt;a href=&quot;#业务需求-7&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;用户希望长期记录阅读进度、读书笔记和兴趣偏好，并在后续对话中快速恢复历史信息。&lt;/p&gt;
&lt;h4&gt;使用组件&lt;a href=&quot;#使用组件-7&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;智能体；&lt;/li&gt;
&lt;li&gt;数据库；&lt;/li&gt;
&lt;li&gt;长期记忆；&lt;/li&gt;
&lt;li&gt;提示词；&lt;/li&gt;
&lt;li&gt;推荐工作流。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;实现效果&lt;a href=&quot;#实现效果-7&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;用户输入阅读书目、页码和笔记后，系统将信息保存到数据库。用户下次询问时，智能体可以恢复阅读进度，并根据历史笔记提供内容回顾或延伸阅读建议。&lt;/p&gt;
&lt;h3&gt;英语外教&lt;a href=&quot;#英语外教&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;业务需求&lt;a href=&quot;#业务需求-8&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;学习者需要随时进行口语练习、语法纠错和情景对话。&lt;/p&gt;
&lt;h4&gt;使用组件&lt;a href=&quot;#使用组件-8&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;智能体；&lt;/li&gt;
&lt;li&gt;大语言模型；&lt;/li&gt;
&lt;li&gt;角色提示词；&lt;/li&gt;
&lt;li&gt;语音工具；&lt;/li&gt;
&lt;li&gt;学习记录数据库。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;实现效果&lt;a href=&quot;#实现效果-8&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;智能体模拟英语教师，与用户开展不同场景的英语对话，并根据用户水平调整难度。系统还可以保存常见错误和学习进度，提供个性化练习建议。&lt;/p&gt;
&lt;h3&gt;内容创作助手&lt;a href=&quot;#内容创作助手&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;业务需求&lt;a href=&quot;#业务需求-9&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;运营人员需要快速完成文案构思、内容改写、标题生成和多平台风格转换。&lt;/p&gt;
&lt;h4&gt;使用组件&lt;a href=&quot;#使用组件-9&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;AI 应用；&lt;/li&gt;
&lt;li&gt;大语言模型；&lt;/li&gt;
&lt;li&gt;提示词模板；&lt;/li&gt;
&lt;li&gt;工作流；&lt;/li&gt;
&lt;li&gt;知识库。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;实现效果&lt;a href=&quot;#实现效果-9&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;用户输入主题、受众和内容要求后，系统按照预设工作流生成大纲、初稿、标题和不同平台版本，并根据品牌知识库保持统一的表达风格。&lt;/p&gt;
&lt;h2&gt;Coze 平台优势&lt;a href=&quot;#coze-平台优势&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;开发门槛低&lt;a href=&quot;#开发门槛低&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Coze 提供可视化开发环境。用户可以通过表单配置、自然语言提示词和拖拽节点完成应用构建，不必从底层编写完整的大模型调用、工具调度和流程控制代码。&lt;/p&gt;
&lt;p&gt;这使产品、运营、教师和业务人员也能够参与 AI 应用设计。&lt;/p&gt;
&lt;h3&gt;工作流编排灵活&lt;a href=&quot;#工作流编排灵活&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;工作流能够将复杂任务拆分为多个节点，并支持条件判断、循环、代码处理、模型调用和插件调用。&lt;/p&gt;
&lt;p&gt;与单次模型问答相比，工作流具有以下优势：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;业务步骤清晰；&lt;/li&gt;
&lt;li&gt;输入输出明确；&lt;/li&gt;
&lt;li&gt;执行过程可观察；&lt;/li&gt;
&lt;li&gt;复杂逻辑可控制；&lt;/li&gt;
&lt;li&gt;流程可以重复使用。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;插件扩展能力强&lt;a href=&quot;#插件扩展能力强&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;大语言模型自身不能直接获取所有实时信息，也不能直接操作企业系统。插件使智能体能够连接搜索、天气、地图、邮件、图像生成以及企业内部 API。&lt;/p&gt;
&lt;p&gt;官方开源文档将插件分为官方内置插件、自定义插件和商业版插件等类型。&lt;/p&gt;
&lt;h3&gt;支持企业专属知识库&lt;a href=&quot;#支持企业专属知识库&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;知识库使智能体能够基于企业自己的资料回答问题，解决通用模型不了解内部业务知识的问题。&lt;/p&gt;
&lt;p&gt;其价值主要体现在：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;统一企业知识入口；&lt;/li&gt;
&lt;li&gt;减少重复咨询；&lt;/li&gt;
&lt;li&gt;提升专业回答准确性；&lt;/li&gt;
&lt;li&gt;缩短员工查找资料的时间；&lt;/li&gt;
&lt;li&gt;支持产品、制度和技术文档问答。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;支持数据库和长期记忆&lt;a href=&quot;#支持数据库和长期记忆&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Coze 可以将对话中的关键信息转化为结构化数据，并在后续任务中重新使用。&lt;/p&gt;
&lt;p&gt;这使智能体能够：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;记住用户偏好；&lt;/li&gt;
&lt;li&gt;跟踪任务进度；&lt;/li&gt;
&lt;li&gt;保存历史状态；&lt;/li&gt;
&lt;li&gt;提供连续服务；&lt;/li&gt;
&lt;li&gt;实现个性化推荐。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;支持快速调试和迭代&lt;a href=&quot;#支持快速调试和迭代&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;平台提供实时预览和调试区域。开发者可以在发布前反复测试提示词、插件、知识库和工作流，并根据结果及时修改配置。&lt;/p&gt;
&lt;p&gt;这种开发方式缩短了从创意验证到应用上线的周期。&lt;/p&gt;
&lt;h3&gt;支持多种集成方式&lt;a href=&quot;#支持多种集成方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Coze 的智能体和应用可以独立运行，也可以通过 API 和 SDK 接入现有网站、企业管理系统和其他软件。&lt;/p&gt;
&lt;p&gt;这使平台既适合快速制作独立 AI 应用，也适合为已有系统增加 AI 能力。&lt;/p&gt;
&lt;h3&gt;支持私有化部署和二次开发&lt;a href=&quot;#支持私有化部署和二次开发&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Coze Studio 是 Coze 核心能力的开源实现，可在本地或企业服务器中部署，并允许开发团队基于源代码进行定制。&lt;/p&gt;
&lt;p&gt;该能力适合：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对数据安全要求较高的企业；&lt;/li&gt;
&lt;li&gt;需要在内网运行的单位；&lt;/li&gt;
&lt;li&gt;需要接入私有系统的项目；&lt;/li&gt;
&lt;li&gt;需要修改平台功能的研发团队。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;需要注意，私有化部署仍然需要进行账户权限、接口安全、数据隔离和运行环境等方面的安全配置。&lt;/p&gt;
&lt;h2&gt;Coze 平台使用流程&lt;a href=&quot;#coze-平台使用流程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Coze 官网版（云端版）&lt;a href=&quot;#coze-官网版云端版-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;创建智能体&lt;a href=&quot;#创建智能体&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;登录扣子平台，在主界面找到并点击创建按钮，即可正式开启智能体的个性化搭建流程。&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://www.coze.cn/space&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://lf-coze-web-cdn.coze.cn/obj/coze-web-cn/obric/coze/favicon.1970.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;coze.cn&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;扣子 - AI Agent智能办公平台 - 扣子用AI重塑生产力与工作效率&lt;/h3&gt;
        &lt;p&gt;扣子(Coze)是基于AI Agent的智能办公平台，提供AI写作、PPT生成、网页开发与AI设计等一体化生产力工具，扣子致力于为用户与企业提供高效、安全、便捷的智能办公新体验。&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://www.coze.cn/space&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185024481.png&quot; alt=&quot;image-20260731212330133&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731212330133&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185032462.png&quot; alt=&quot;image-20260731212428935&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731212428935&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;为智能体起一个独特的名字，并简洁描述其功能定位与服务场景，明确其角色价值。&lt;/p&gt;
&lt;p&gt;支持系统自动生成风格多样的头像，也可上传品牌 Logo 或个人设计的专属形象，让智能体拥有独一无二的视觉标识。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185034606.png&quot; alt=&quot;image-20260731212856892&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731212856892&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;确认基础信息无误后点击确认，系统将跳转至智能体编排核心页面，接下来即可进行逻辑配置与功能开发。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185036404.png&quot; alt=&quot;image-20260731213502911&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731213502911&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;编写提示词&lt;a href=&quot;#编写提示词&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;配置智能体的核心是编写提示词（Prompt），也就是为它定义专属的人设与底层回复逻辑。一个精准、清晰的提示词，能让智能体的行为模式与输出结果更贴合我们的预期，从而高效完成特定任务。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185037949.png&quot; alt=&quot;image-20260731213128748&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731213128748&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;添加知识库&lt;a href=&quot;#添加知识库&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;基础模型的原生能力不足以支撑政务查下业务场景的复杂需求，需要为智能体主动添加技能和知识库。&lt;/p&gt;
&lt;p&gt;这一步能有效突破模型的知识截止时间与固有能力边界，让智能体具备实时信息获取、工具调用等进阶能力，解决单纯依赖大模型无法完成的实际问题。&lt;/p&gt;
&lt;p&gt;这里选择添加知识库&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185039977.png&quot; alt=&quot;image-20260731213409825&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731213409825&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;此时我们还没有知识库，需要新创建一个知识库&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185041812.png&quot; alt=&quot;image-20260731213424043&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731213424043&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这里我们选择创建扣子知识库，并选择文本格式，填写相关名称和描述&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185043486.png&quot; alt=&quot;image-20260731213553673&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731213553673&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;选择本地文档的导入类型并更改图标，点击创建并导入即可创建一个新的知识库&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185337555.png&quot; alt=&quot;image-20260731213855779&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731213855779&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;随后，我们需要上传相关文件，等待解析完成后，点击下一步&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185047214.png&quot; alt=&quot;image-20260731214105845&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731214105845&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这里我们选择默认设置，并下一步&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185048752.png&quot; alt=&quot;image-20260731214931354&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731214931354&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这里可以看到分段预览结果，确认无误后点击下一步&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185052243.png&quot; alt=&quot;image-20260731215052516&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731215052516&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这里会提交给服务器处理，无需等待，点击确认即可&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185052864.png&quot; alt=&quot;image-20260731215156643&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731215156643&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;如果有需要可以在这一页添加新的内容，这里我们选择添加到智能体&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185056367.png&quot; alt=&quot;image-20260731215235143&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731215235143&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;添加工作流&lt;a href=&quot;#添加工作流&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;这里选择添加工作流&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185340659.png&quot; alt=&quot;image-20260731221716379&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731221716379&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;因为我们还没有工作流，需要创建一个，这里我们选择创建对话流&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185101185.png&quot; alt=&quot;image-20260731221751120&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731221751120&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这里需要添加对话流的名称和描述&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185101416.png&quot; alt=&quot;image-20260731221919605&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731221919605&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这里通过可视化的操作完成对话流的搭建&lt;/p&gt;
&lt;p&gt;先创建知识库检索节点，并用鼠标将开始节点和知识库检索节点连接在一起&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185102246.png&quot; alt=&quot;image-20260731225651341&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731225651341&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;点击知识库检索节点，从输入变量中选择开始节点的 USER_INPUT，并配置已有的知识库&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185113312.png&quot; alt=&quot;image-20260731225719512&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731225719512&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185115384.png&quot; alt=&quot;image-20260731225844902&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731225844902&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;添加大模型节点，并将知识库检索节点和知识库检索节点，结束节点连接在一起&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185115847.png&quot; alt=&quot;image-20260731225746853&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731225746853&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;大模型节点需要两个输入变量，一个是开始的 USER_INPUT，一个是知识库检索的 outputList&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185116970.png&quot; alt=&quot;image-20260731225935956&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731225935956&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;此节点还需要配置系统提示词和用户提示词&lt;/p&gt;
&lt;p&gt;系统提示词和用户提示词需要通过 {{}}引用输入变量，例如&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;用户问题：&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;{{input1}}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;知识库检索结果：&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;{{input}}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;请根据以上知识库检索结果回答用户问题。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185117096.png&quot; alt=&quot;image-20260731230124276&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731230124276&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;结束节点的输出变量选择大模型节点的 output，回答内容添加 {{output}}&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185245538.png&quot; alt=&quot;image-20260731230403762&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731230403762&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;点击试运行进行测试&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185124951.png&quot; alt=&quot;image-20260731230608256&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731230608256&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185129003.png&quot; alt=&quot;image-20260731230721718&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731230721718&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;点击右上角发布对话流，并添加到当前智能体中&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185249276.png&quot; alt=&quot;image-20260731230742354&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731230742354&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;调试智能体&lt;a href=&quot;#调试智能体&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;在右侧的预览与调试区域，像和真人聊天一样与你的机器人对话。通过实际的交互流程，全方位测试它的回答准确度、逻辑连贯性以及是否符合你的业务预期。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185134541.png&quot; alt=&quot;image-20260731230929929&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731230929929&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;发布智能体&lt;a href=&quot;#发布智能体&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;完成所有测试与参数配置后，只需点击“发布”按钮，即可将智能体正式部署。系统将自动处理后端配置，让你的智能体在目标渠道上线，开始为用户提供服务。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185252422.png&quot; alt=&quot;image-20260731220032268&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731220032268&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这里我们选择确认&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185136926.png&quot; alt=&quot;image-20260731220147129&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731220147129&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;这里需要选择发布渠道，默认会选择扣子商店，默认即可&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185138617.png&quot; alt=&quot;image-20260731220240325&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731220240325&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;等待审核过后，即可发布成功，发布成功后即可在作品社区中搜索到&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185148225.png&quot; alt=&quot;image-20260731220355426&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731220355426&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185255758.png&quot; alt=&quot;image-20260731231646282&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731231646282&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;Coze Studio（开源版）&lt;a href=&quot;#coze-studio开源版-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;安装环境&lt;a href=&quot;#安装环境&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;首先需要安装 Docker Desktop&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://www.docker.com/products/docker-desktop/&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://www.docker.com/app/uploads/2024/02/cropped-docker-logo-favicon-270x270.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;docker.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;Docker Desktop: The #1 Containerization Tool for Developers | Docker&lt;/h3&gt;
        &lt;p&gt;Docker Desktop is collaborative containerization software for developers. Get started and download Docker Desktop today on Mac, Windows, or Linux.&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://www.docker.com/products/docker-desktop/&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://www.docker.com/app/uploads/2023/06/meta-image-download-docker-desktop-1110x580.png&quot; alt=&quot;Docker Desktop: The #1 Containerization Tool for Developers | Docker&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;然后从 Github 下载 Coze Studio 的源码&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://github.com/coze-dev/coze-studio&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://github.com/fluidicon.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;github.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;GitHub - coze-dev/coze-studio: An AI agent development platform with all-in-one visual tools, simplifying agent creation, debugging, and deployment like never before. Coze your way to AI Agent creation.&lt;/h3&gt;
        &lt;p&gt;An AI agent development platform with all-in-one visual tools, simplifying agent creation, debugging, and deployment like never before. Coze your way to AI Agent creation. - coze-dev/coze-studio&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://github.com/coze-dev/coze-studio&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://opengraph.githubassets.com/8488aad2fc677444aa926551f932ea8cf3d15ae07fc584270f909389c19b19b7/coze-dev/coze-studio&quot; alt=&quot;GitHub - coze-dev/coze-studio: An AI agent development platform with all-in-one visual tools, simplifying agent creation, debugging, and deployment like never before. Coze your way to AI Agent creation.&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185155363.png&quot; alt=&quot;image-20260801142653864&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260801142653864&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;全部解压后，在 coze-studio\docker 下打开终端，输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; compose&lt;/span&gt;&lt;span&gt; up&lt;/span&gt;&lt;span&gt; -d&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;用于启动服务&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185258976.png&quot; alt=&quot;image-20260801142828297&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260801142828297&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;注册账号，访问  &lt;a href=&quot;http://localhost:8888/sign&quot;&gt;http://localhost:8888/sign&lt;/a&gt; 输入用户名、密码点击注册按钮，然后会来到此页面&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185156284.png&quot; alt=&quot;image-20260801142946562&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260801142946562&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;配置模型&lt;a href=&quot;#配置模型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;h5&gt;获取向量模型&lt;a href=&quot;#获取向量模型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;首先下载 ollama 用于调用本地模型，下载链接为&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://ollama.com/download/windows&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://ollama.com/public/apple-touch-icon.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;ollama.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;Download Ollama on Windows&lt;/h3&gt;
        &lt;p&gt;Download Ollama for Windows&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://ollama.com/download/windows&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://ollama.com/public/og.png&quot; alt=&quot;Download Ollama on Windows&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;然后打开 终端 ，输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;ollama&lt;/span&gt;&lt;span&gt; pull&lt;/span&gt;&lt;span&gt; bge-m3:567m-fp16&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此命令用于下载本地模型，下载完成后查看：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;ollama&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;获取语言模型&lt;a href=&quot;#获取语言模型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;首先登录阿里云百炼控制台&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://bailian.console.aliyun.com/&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://img.alicdn.com/imgextra/i1/O1CN01Es0c28049TL083Vo_!!6000000002263-2-tps-64-64.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;bailian.console.aliyun.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;大模型服务平台百炼控制台&lt;/h3&gt;
        &lt;p&gt;百炼控制台是阿里云大模型服务平台，提供AI模型训练、部署、推理一站式服务，支持多种大模型框架，助力企业快速构建AI应用。&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://bailian.console.aliyun.com/&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://img.alicdn.com/imgextra/i1/O1CN01Es0c28049TL083Vo_!!6000000002263-2-tps-64-64.png&quot; alt=&quot;大模型服务平台百炼控制台&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;然后申请一个 API Key&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://bailian.console.aliyun.com/cn-beijing?tab=model#/api-key&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://img.alicdn.com/imgextra/i1/O1CN01Es0c28049TL083Vo_!!6000000002263-2-tps-64-64.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;bailian.console.aliyun.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;大模型服务平台百炼控制台&lt;/h3&gt;
        &lt;p&gt;百炼控制台是阿里云大模型服务平台，提供AI模型训练、部署、推理一站式服务，支持多种大模型框架，助力企业快速构建AI应用。&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://bailian.console.aliyun.com/cn-beijing?tab=model#/api-key&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://img.alicdn.com/imgextra/i1/O1CN01Es0c28049TL083Vo_!!6000000002263-2-tps-64-64.png&quot; alt=&quot;大模型服务平台百炼控制台&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185156310.png&quot; alt=&quot;image-20260801141929926&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260801141929926&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185158272.png&quot; alt=&quot;image-20260801142006022&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260801142006022&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;复制密钥和请求地址&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185302689.png&quot; alt=&quot;image-20260801143218724&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260801143218724&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;访问 &lt;a href=&quot;http://localhost:8888/admin/#model-management&quot;&gt;Coze Studio 管理后台&lt;/a&gt; ，下滑选择 Qwen 家族&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185205718.png&quot; alt=&quot;image-20260801143323026&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260801143323026&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;填写模型显示名称和模型类型，并粘贴密钥和地址，然后点击保存&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185209563.png&quot; alt=&quot;image-20260801143420100&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260801143420100&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;随后填写如下信息，然后往下滑，点击保存配置&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185210881.png&quot; alt=&quot;image-20260801143703609&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260801143703609&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;它提示我们重启服务器，我们在 coze-studio\docker 下打开终端，输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; compose&lt;/span&gt;&lt;span&gt; restart&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此时相关服务会重启启动&lt;/p&gt;
&lt;p&gt;随后配置过程与云端版类似，但别忘了修改模型&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260801185216562.png&quot; alt=&quot;image-20260801145920160&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260801145920160&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;Coze 平台适用场景&lt;a href=&quot;#coze-平台适用场景&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;教育教学&lt;a href=&quot;#教育教学&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;适合构建：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI 助教；&lt;/li&gt;
&lt;li&gt;英语口语陪练；&lt;/li&gt;
&lt;li&gt;课程资料问答助手；&lt;/li&gt;
&lt;li&gt;作业辅导助手；&lt;/li&gt;
&lt;li&gt;学习计划工具；&lt;/li&gt;
&lt;li&gt;教学内容生成应用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主要使用智能体、知识库、提示词和学习记录数据库。&lt;/p&gt;
&lt;h3&gt;企业客服&lt;a href=&quot;#企业客服&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;适合构建：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;售前咨询机器人；&lt;/li&gt;
&lt;li&gt;售后服务助手；&lt;/li&gt;
&lt;li&gt;订单查询助手；&lt;/li&gt;
&lt;li&gt;产品使用指导；&lt;/li&gt;
&lt;li&gt;人工客服辅助系统。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主要使用知识库、业务插件、工作流和 API。&lt;/p&gt;
&lt;h3&gt;企业知识管理&lt;a href=&quot;#企业知识管理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;适合构建：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;员工制度问答；&lt;/li&gt;
&lt;li&gt;产品文档助手；&lt;/li&gt;
&lt;li&gt;技术支持知识库；&lt;/li&gt;
&lt;li&gt;项目资料检索；&lt;/li&gt;
&lt;li&gt;新员工培训助手。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主要使用知识库、RAG、权限管理和对话界面。&lt;/p&gt;
&lt;h3&gt;内容创作&lt;a href=&quot;#内容创作&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;适合构建：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文案生成；&lt;/li&gt;
&lt;li&gt;标题生成；&lt;/li&gt;
&lt;li&gt;内容改写；&lt;/li&gt;
&lt;li&gt;报告撰写；&lt;/li&gt;
&lt;li&gt;脚本生成；&lt;/li&gt;
&lt;li&gt;品牌内容助手。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主要使用大语言模型、提示词、工作流和品牌知识库。&lt;/p&gt;
&lt;h3&gt;办公自动化&lt;a href=&quot;#办公自动化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;适合构建：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;会议内容整理；&lt;/li&gt;
&lt;li&gt;邮件生成与分类；&lt;/li&gt;
&lt;li&gt;表格数据处理；&lt;/li&gt;
&lt;li&gt;报告自动生成；&lt;/li&gt;
&lt;li&gt;任务通知；&lt;/li&gt;
&lt;li&gt;日常事务助手。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主要使用工作流、插件、代码节点和数据库。&lt;/p&gt;
&lt;h3&gt;电商与运营&lt;a href=&quot;#电商与运营&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;适合构建：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;商品描述生成；&lt;/li&gt;
&lt;li&gt;用户评论分析；&lt;/li&gt;
&lt;li&gt;智能导购；&lt;/li&gt;
&lt;li&gt;订单信息提取；&lt;/li&gt;
&lt;li&gt;客服自动化；&lt;/li&gt;
&lt;li&gt;营销活动内容生成。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主要使用智能体、工作流、商品知识库和电商系统插件。&lt;/p&gt;
&lt;h3&gt;市场营销与销售&lt;a href=&quot;#市场营销与销售&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;适合构建：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;客户画像分析；&lt;/li&gt;
&lt;li&gt;销售话术推荐；&lt;/li&gt;
&lt;li&gt;市场调研；&lt;/li&gt;
&lt;li&gt;竞品信息整理；&lt;/li&gt;
&lt;li&gt;线索分类；&lt;/li&gt;
&lt;li&gt;营销内容生成。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主要使用数据库、搜索插件、工作流和大语言模型。&lt;/p&gt;
&lt;h3&gt;个人效率工具&lt;a href=&quot;#个人效率工具&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;适合构建：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;个人助理；&lt;/li&gt;
&lt;li&gt;阅读记录助手；&lt;/li&gt;
&lt;li&gt;旅行规划；&lt;/li&gt;
&lt;li&gt;日程管理；&lt;/li&gt;
&lt;li&gt;信息摘要；&lt;/li&gt;
&lt;li&gt;个性化学习助手。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;主要使用智能体、插件、长期记忆和数据库。&lt;/p&gt;
&lt;h3&gt;场景选择参考&lt;a href=&quot;#场景选择参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;需求特征&lt;/th&gt;&lt;th&gt;推荐使用的 Coze 能力&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;需要通过聊天完成任务&lt;/td&gt;&lt;td&gt;智能体&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要固定输入、输出和界面&lt;/td&gt;&lt;td&gt;AI 应用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要执行多个确定步骤&lt;/td&gt;&lt;td&gt;工作流&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要查询实时信息&lt;/td&gt;&lt;td&gt;插件与工具&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要依据企业内部资料回答&lt;/td&gt;&lt;td&gt;知识库与 RAG&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要记住用户偏好和历史状态&lt;/td&gt;&lt;td&gt;数据库与长期记忆&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要接入现有业务系统&lt;/td&gt;&lt;td&gt;API、SDK、自定义插件&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要本地保存数据或深度定制&lt;/td&gt;&lt;td&gt;Coze Studio 私有化部署&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要快速在线体验和完成原型&lt;/td&gt;&lt;td&gt;Coze 官网版&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要研究开源实现或修改平台功能&lt;/td&gt;&lt;td&gt;Coze Studio&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;没有部署运维条件&lt;/td&gt;&lt;td&gt;Coze 官网版&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要在企业内网长期运行&lt;/td&gt;&lt;td&gt;Coze Studio&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;官网版与开源版的选择建议&lt;a href=&quot;#官网版与开源版的选择建议&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;适合选择 Coze 官网版的情况&lt;a href=&quot;#适合选择-coze-官网版的情况&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;第一次学习 Coze，希望快速熟悉核心功能；&lt;/li&gt;
&lt;li&gt;用于课堂演示、课程实验和个人练习；&lt;/li&gt;
&lt;li&gt;需要尽快制作可运行的原型；&lt;/li&gt;
&lt;li&gt;不具备服务器部署和系统运维条件；&lt;/li&gt;
&lt;li&gt;希望直接使用官网提供的在线能力和生态资源；&lt;/li&gt;
&lt;li&gt;项目暂时不涉及高度敏感的内部数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;适合选择 Coze Studio 的情况&lt;a href=&quot;#适合选择-coze-studio-的情况&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;需要在实验室、学校或企业服务器中部署；&lt;/li&gt;
&lt;li&gt;需要控制数据存放位置和运行环境；&lt;/li&gt;
&lt;li&gt;需要接入内部数据库、模型或业务系统；&lt;/li&gt;
&lt;li&gt;需要修改平台源代码；&lt;/li&gt;
&lt;li&gt;需要研究智能体、工作流、RAG 和插件的实现方式；&lt;/li&gt;
&lt;li&gt;团队具备 Docker、服务器和软件开发能力。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;总结&lt;a href=&quot;#总结&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Coze 的核心价值并不只是提供大语言模型对话，而是把模型、提示词、智能体、工作流、插件、知识库、数据库和发布能力整合为一个完整的低代码 AI 应用开发平台。&lt;/p&gt;
&lt;p&gt;从产品能力架构来看：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;大语言模型提供理解、推理和生成能力；&lt;/li&gt;
&lt;li&gt;智能体负责接收用户目标并组织任务执行；&lt;/li&gt;
&lt;li&gt;工作流负责稳定地编排复杂业务逻辑；&lt;/li&gt;
&lt;li&gt;插件和工具负责连接外部服务；&lt;/li&gt;
&lt;li&gt;知识库为应用提供专业和私有知识；&lt;/li&gt;
&lt;li&gt;数据库与长期记忆负责保存业务状态；&lt;/li&gt;
&lt;li&gt;可视化工作台、调试和发布能力支撑应用开发全过程。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在使用形态上，Coze 官网版和 Coze Studio 分别满足不同需求：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Coze 官网版&lt;/strong&gt;侧重开箱即用，适合初学者、课程教学、个人体验和快速原型验证；&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coze Studio&lt;/strong&gt;侧重私有化和自主扩展，适合技术研究、企业内网部署和深度二次开发。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;资料来源&lt;a href=&quot;#资料来源&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Coze Studio 官方 GitHub 仓库&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://github.com/coze-dev/coze-studio&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://github.com/fluidicon.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;github.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;GitHub - coze-dev/coze-studio: An AI agent development platform with all-in-one visual tools, simplifying agent creation, debugging, and deployment like never before. Coze your way to AI Agent creation.&lt;/h3&gt;
        &lt;p&gt;An AI agent development platform with all-in-one visual tools, simplifying agent creation, debugging, and deployment like never before. Coze your way to AI Agent creation. - coze-dev/coze-studio&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://github.com/coze-dev/coze-studio&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://opengraph.githubassets.com/8488aad2fc677444aa926551f932ea8cf3d15ae07fc584270f909389c19b19b7/coze-dev/coze-studio&quot; alt=&quot;GitHub - coze-dev/coze-studio: An AI agent development platform with all-in-one visual tools, simplifying agent creation, debugging, and deployment like never before. Coze your way to AI Agent creation.&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Coze Studio 官方 Wiki：什么是 Coze Studio&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://github.com/coze-dev/coze-studio/wiki/1.-%E4%BB%80%E4%B9%88%E6%98%AF-Coze-Studio&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://github.com/fluidicon.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;github.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;1. 什么是 Coze Studio&lt;/h3&gt;
        &lt;p&gt;An AI agent development platform with all-in-one visual tools, simplifying agent creation, debugging, and deployment like never before. Coze your way to AI Agent creation. - coze-dev/coze-studio&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://github.com/coze-dev/coze-studio/wiki/1.-%E4%BB%80%E4%B9%88%E6%98%AF-Coze-Studio&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://opengraph.githubassets.com/8488aad2fc677444aa926551f932ea8cf3d15ae07fc584270f909389c19b19b7/coze-dev/coze-studio&quot; alt=&quot;1. 什么是 Coze Studio&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Coze Studio 官方 Wiki：插件配置&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://github.com/coze-dev/coze-studio/wiki/4.-%E6%8F%92%E4%BB%B6%E9%85%8D%E7%BD%AE&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://github.com/fluidicon.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;github.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;4. 插件配置&lt;/h3&gt;
        &lt;p&gt;An AI agent development platform with all-in-one visual tools, simplifying agent creation, debugging, and deployment like never before. Coze your way to AI Agent creation. - coze-dev/coze-studio&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://github.com/coze-dev/coze-studio/wiki/4.-%E6%8F%92%E4%BB%B6%E9%85%8D%E7%BD%AE&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://opengraph.githubassets.com/8488aad2fc677444aa926551f932ea8cf3d15ae07fc584270f909389c19b19b7/coze-dev/coze-studio&quot; alt=&quot;4. 插件配置&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Coze 官方文档中心&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://www.coze.cn/docs/&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://lf-coze-web-cdn.coze.cn/obj/coze-web-cn/obric/coze/favicon.1970.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;coze.cn&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;扣子 - AI Agent智能办公平台 - 扣子用AI重塑生产力与工作效率&lt;/h3&gt;
        &lt;p&gt;扣子(Coze)是基于AI Agent的智能办公平台，提供AI写作、PPT生成、网页开发与AI设计等一体化生产力工具，扣子致力于为用户与企业提供高效、安全、便捷的智能办公新体验。&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://www.coze.cn/docs/&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Coze 官网产品概览&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://www.coze.cn/overview&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://www.coze.cn/space-intro/favicon.ico&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;coze.cn&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;扣子 Coze - 字节跳动旗下职场AI伙伴扣子与一站式AI开发平台扣子编程 PPT数据分析小程序开发APP开发网页开发平面设计教学备课报告写作自媒体播客视频智能体工作流&lt;/h3&gt;
        &lt;p&gt;职场AI就用扣子，字节跳动旗下职场AI与一站式AI开发平台，可操作电脑和手机，直接交付结果，好用易上手。如何用AI提升教学、科研和行政效率？怎么用AI做自媒体内容和朋友圈内容？用AI开发和部署官网、活动营销页面、网页应用？想用AI分析竞品、策划营销、打造爆款、写述职报告、做转正PPT？无需复杂指令，在扣子和扣子编程用AI轻松搞定。&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://www.coze.cn/overview&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Coze Studio 英文 Wiki：What is Coze Studio&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://github.com/coze-dev/coze-studio/wiki/1.-What-is-Coze-Studio&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://github.com/fluidicon.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;github.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;1. What is Coze Studio&lt;/h3&gt;
        &lt;p&gt;An AI agent development platform with all-in-one visual tools, simplifying agent creation, debugging, and deployment like never before. Coze your way to AI Agent creation. - coze-dev/coze-studio&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://github.com/coze-dev/coze-studio/wiki/1.-What-is-Coze-Studio&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://opengraph.githubassets.com/8488aad2fc677444aa926551f932ea8cf3d15ae07fc584270f909389c19b19b7/coze-dev/coze-studio&quot; alt=&quot;1. What is Coze Studio&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>category:实验室</category><category>tag:Coze</category><category>tag:技术文档</category></item><item><title>巡云论坛部署文档</title><link>https://blog.hoshiumi.xyz/post/lab/xun-yun-lun-tan-bu-shu-wen-dang</link><guid isPermaLink="false">lab/xun-yun-lun-tan-bu-shu-wen-dang</guid><description>巡云论坛部署文档

在 Windows 下打包，发送到服务器上运行

Windows 环境搭建
安装 java
采用 jvms 管理 java 版本，如果已经有 java 8 请忽略
下载 jvms
访问</description><pubDate>Fri, 31 Jul 2026 11:24:33 GMT</pubDate><content:encoded>&lt;h1&gt;巡云论坛部署文档&lt;a href=&quot;#巡云论坛部署文档&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;在 Windows 下打包，发送到服务器上运行&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Windows 环境搭建&lt;a href=&quot;#windows-环境搭建&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;安装 java&lt;a href=&quot;#安装-java&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;采用 jvms 管理 java 版本，如果已经有 java 8 请忽略&lt;/p&gt;
&lt;h4&gt;下载 jvms&lt;a href=&quot;#下载-jvms&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;访问&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://github.com/ystyle/jvms/releases&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://github.com/fluidicon.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;github.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;Releases · ystyle/jvms&lt;/h3&gt;
        &lt;p&gt;JDK Version Manager (JVMS) for Windows. Contribute to ystyle/jvms development by creating an account on GitHub.&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://github.com/ystyle/jvms/releases&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://opengraph.githubassets.com/7e39d0c3f6f98d9e638fd6e28c9bb12b23092738f00f26e71db207551f3c3e9a/ystyle/jvms&quot; alt=&quot;Releases · ystyle/jvms&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;下载最新版本&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192115044.png&quot; alt=&quot;image-20260731150347748&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731150347748&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;推荐解压到&lt;code&gt;C:\java&lt;/code&gt;&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192109298.png&quot; alt=&quot;image-20260731151058683&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731151058683&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;初始化 jvms&lt;a href=&quot;#初始化-jvms&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;在 Windows 设置上搜索&lt;code&gt;编辑系统环境变量&lt;/code&gt;&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192122999.png&quot; alt=&quot;image-20260731151310087&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731151310087&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192125770.png&quot; alt=&quot;image-20260731151335163&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731151335163&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;双击 Path&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192127371.png&quot; alt=&quot;image-20260731151516541&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731151516541&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;新建这一条记录&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192128642.png&quot; alt=&quot;image-20260731151532601&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731151532601&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;然后，打开 powershell ，输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;jvms&lt;/span&gt;&lt;span&gt; init&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192245746.png&quot; alt=&quot;image-20260731151714920&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731151714920&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;下载 java 8&lt;a href=&quot;#下载-java-8&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;下载地址为：&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://mirrors.tuna.tsinghua.edu.cn/Adoptium/8/jdk/x64/windows/&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;https://mirrors.tuna.tsinghua.edu.cn/Adoptium/8/jdk/x64/windows/&lt;/div&gt;
          &lt;div&gt;mirrors.tuna.tsinghua.edu.cn&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      
        
      
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192132226.png&quot; alt=&quot;image-20260731151911731&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731151911731&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192134123.png&quot; alt=&quot;image-20260731152034017&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731152034017&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192135491.png&quot; alt=&quot;image-20260731152049403&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731152049403&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192136961.png&quot; alt=&quot;image-20260731152105412&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731152105412&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192138576.png&quot; alt=&quot;image-20260731152127622&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731152127622&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192139968.png&quot; alt=&quot;image-20260731152205558&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731152205558&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192141418.png&quot; alt=&quot;image-20260731152420044&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731152420044&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192142732.png&quot; alt=&quot;image-20260731152457290&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731152457290&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192144087.png&quot; alt=&quot;image-20260731152801977&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731152801977&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;启用 java 8&lt;a href=&quot;#启用-java-8&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;在 powershell 中输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;jvms&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看本机中由 jvms 管理的 java 版本，然后输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;jvms&lt;/span&gt;&lt;span&gt; switch&lt;/span&gt;&lt;span&gt; [ &lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt; 前面的数字]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192146849.png&quot; alt=&quot;image-20260731153136986&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731153136986&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;验证安装&lt;a href=&quot;#验证安装&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;在 powershell 输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;java&lt;/span&gt;&lt;span&gt; -version&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192148920.png&quot; alt=&quot;image-20260731154358950&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731154358950&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;安装 maven&lt;a href=&quot;#安装-maven&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;下载&lt;a href=&quot;#下载&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;下载链接为&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://maven.apache.org/download.cgi&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://apache.org/favicon.ico&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;maven.apache.org&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;Download Apache Maven – Maven&lt;/h3&gt;
        
        &lt;div&gt;
          &lt;span&gt;https://maven.apache.org/download.cgi&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://maven.apache.org/images/apache-maven-project-light-theme.svg&quot; alt=&quot;Download Apache Maven – Maven&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192150303.png&quot; alt=&quot;image-20260731153339688&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731153339688&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;解压&lt;a href=&quot;#解压&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;将压缩包解压到&lt;code&gt;C:\maven&lt;/code&gt;&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192151844.png&quot; alt=&quot;image-20260731153428512&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731153428512&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;配置&lt;a href=&quot;#配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;修改配置文件&lt;code&gt;C:\maven\conf\settings.xml&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;在&amp;lt;mirrors&amp;gt;和 &amp;lt;/mirrors&amp;gt; 之间添加&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;mirror&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;&amp;gt;aliyun&amp;lt;/&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span&gt;mirrorOf&lt;/span&gt;&lt;span&gt;&amp;gt;central&amp;lt;/&lt;/span&gt;&lt;span&gt;mirrorOf&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;&amp;gt;aliyun maven&amp;lt;/&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;&amp;gt;https://maven.aliyun.com/repository/public&amp;lt;/&lt;/span&gt;&lt;span&gt;url&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;mirror&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此配置用于设置 maven 镜像仓库地址&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192153916.png&quot; alt=&quot;image-20260731153655968&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731153655968&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;在&amp;lt;settings&amp;gt;和&amp;lt;/settings&amp;gt;之间添加&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;localRepository&lt;/span&gt;&lt;span&gt;&amp;gt;E:\m2&amp;lt;/&lt;/span&gt;&lt;span&gt;localRepository&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此配置用于设置 maven 本地仓库地址，尽量改成 C 盘以外&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192253014.png&quot; alt=&quot;image-20260731154128693&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731154128693&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;在系统环境变量中添加&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192155785.png&quot; alt=&quot;image-20260731154251729&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731154251729&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;验证安装&lt;a href=&quot;#验证安装-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;在 powershell 输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;mvn&lt;/span&gt;&lt;span&gt; -v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192158047.png&quot; alt=&quot;image-20260731154504736&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731154504736&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;安装 Git&lt;a href=&quot;#安装-git&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;下载&lt;a href=&quot;#下载-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;下载链接为&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://git-scm.com/install/windows&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://git-scm.com/favicon.ico&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;git-scm.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;Git - Install for Windows&lt;/h3&gt;
        
        &lt;div&gt;
          &lt;span&gt;https://git-scm.com/install/windows&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://git-scm.com/images/icons/nav-read-book.png&quot; alt=&quot;Git - Install for Windows&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192200012.png&quot; alt=&quot;image-20260731154621281&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731154621281&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;安装过程中，默认配置就行，一直按下一步，直到安装成功&lt;/p&gt;
&lt;h4&gt;验证安装&lt;a href=&quot;#验证安装-2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;在 powershell 输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; -v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192202492.png&quot; alt=&quot;image-20260731154755495&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731154755495&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;安装 Docker Desktop&lt;a href=&quot;#安装-docker-desktop&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;下载&lt;a href=&quot;#下载-2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;下载地址为&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://www.docker.com/products/docker-desktop/&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://www.docker.com/app/uploads/2024/02/cropped-docker-logo-favicon-270x270.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;docker.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;Docker Desktop: The #1 Containerization Tool for Developers | Docker&lt;/h3&gt;
        &lt;p&gt;Docker Desktop is collaborative containerization software for developers. Get started and download Docker Desktop today on Mac, Windows, or Linux.&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://www.docker.com/products/docker-desktop/&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://www.docker.com/app/uploads/2023/06/meta-image-download-docker-desktop-1110x580.png&quot; alt=&quot;Docker Desktop: The #1 Containerization Tool for Developers | Docker&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192204020.png&quot; alt=&quot;image-20260731154932093&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731154932093&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h4&gt;配置&lt;a href=&quot;#配置-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;建议重写 Docker Engine&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192205483.png&quot; alt=&quot;image-20260731155106237&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731155106237&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;如果你使用 &lt;a href=&quot;https://xuanyuan.cloud/&quot;&gt;轩辕镜像&lt;/a&gt; 请将 配置修改为&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;builder&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &quot;gc&quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &quot;defaultKeepStorage&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&quot;30GB&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      &quot;enabled&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  },&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;experimental&quot;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;insecure-registries&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &quot;******.xuanyuan.run&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  ],&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &quot;registry-mirrors&quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &quot;https://******.xuanyuan.run&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;安装 node&lt;a href=&quot;#安装-node&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用 nvm 管理 node 版本&lt;/p&gt;
&lt;h4&gt;下载 nvm&lt;a href=&quot;#下载-nvm&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;下载链接为&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://nvm.uihtm.com/doc/download-nvm.html&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://nvm.uihtm.com/favicon.ico&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;nvm.uihtm.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;开始 下载nvm - nvm中文官网&lt;/h3&gt;
        &lt;p&gt;nvm内容管理框架&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://nvm.uihtm.com/doc/download-nvm.html&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://nvm.uihtm.com/images/logo.png&quot; alt=&quot;开始 下载nvm - nvm中文官网&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192208078.png&quot; alt=&quot;image-20260731161340244&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731161340244&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;然后同意协议，默认配置，并安装&lt;/p&gt;
&lt;h4&gt;配置 nvm&lt;a href=&quot;#配置-nvm&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;在 powershell 中运行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;# 注意结尾有斜杠&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; node_mirror&lt;/span&gt;&lt;span&gt; https://npmmirror.com/mirrors/node/&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; npm_mirror&lt;/span&gt;&lt;span&gt; https://npmmirror.com/mirrors/npm/&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此配置用于设置国内镜像源&lt;/p&gt;
&lt;h4&gt;安装 node&lt;a href=&quot;#安装-node-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;在 powershell 中运行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;# 输出安装版本&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; -v&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 安装 node 22&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; 22&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 使用 node 22&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; use&lt;/span&gt;&lt;span&gt; 22&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;配置 node&lt;a href=&quot;#配置-node&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;在 powershell 中运行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; set&lt;/span&gt;&lt;span&gt; registry&lt;/span&gt;&lt;span&gt; https://registry.npmmirror.com&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此配置用于设置国内镜像源&lt;/p&gt;
&lt;h2&gt;程序打包并拷贝&lt;a href=&quot;#程序打包并拷贝&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;启动 mysql&lt;a href=&quot;#启动-mysql&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 D 盘打开 powershell 并运行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;git&lt;/span&gt;&lt;span&gt; clone&lt;/span&gt;&lt;span&gt; https://gitee.com/qinzihang2006/blog.git&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192210603.png&quot; alt=&quot;image-20260731155632133&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731155632133&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;在&lt;code&gt;D:\blog&lt;/code&gt;下运行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;docker&lt;/span&gt;&lt;span&gt; compose&lt;/span&gt;&lt;span&gt; up&lt;/span&gt;&lt;span&gt; mysql&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在出现&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192212374.png&quot; alt=&quot;image-20260731160035489&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731160035489&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;时，就可以退出了，它会在后台运行&lt;/p&gt;
&lt;h3&gt;修改配置文件&lt;a href=&quot;#修改配置文件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;将&lt;code&gt;D:\blog\bbs-web-admin\.env.production&lt;/code&gt;中的&lt;code&gt;VITE_API_URL&lt;/code&gt;的值改为服务器真实的 ip 地址&lt;/p&gt;
&lt;p&gt;将&lt;code&gt;D:\blog\bbs-web-mobile\.env.production&lt;/code&gt; 中的&lt;code&gt;VITE_API_URL&lt;/code&gt;的值改为服务器真实的 ip 地址&lt;/p&gt;
&lt;p&gt;将&lt;code&gt;D:\blog\bbs-web-pc\.env.production&lt;/code&gt;中的&lt;code&gt;VITE_API_URL&lt;/code&gt;的值改为服务器真实的 ip 地址&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;D:\blog\src\main\resources\crossOrigin.properties&lt;/code&gt;中添加跨域请求的地址，例如&lt;code&gt;http://10.1.100.104&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;安装依赖&lt;a href=&quot;#安装依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在&lt;code&gt;D:\blog&lt;/code&gt;下运行&lt;code&gt;mvn install&lt;/code&gt;，下载后端相关依赖&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;D:\blog\bbs-web-mobile&lt;/code&gt;下运行&lt;code&gt;npm install&lt;/code&gt;，下载 mobile 端依赖&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;D:\blog\bbs-web-admin&lt;/code&gt;下运行&lt;code&gt;npm install&lt;/code&gt;，下载 admin 端依赖&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;D:\blog\bbs-web-pc&lt;/code&gt;下运行&lt;code&gt;npm install&lt;/code&gt;，下载 web 端依赖&lt;/p&gt;
&lt;h3&gt;测试运行&lt;a href=&quot;#测试运行&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在&lt;code&gt;D:\blog&lt;/code&gt;下运行&lt;code&gt;mvn spring-boot:run&lt;/code&gt;，如果出现类似于&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;16:28:47 INFO  cms.Application - Started Application in 5.304 seconds (JVM running for 5.962)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;并且无报错信息，默认可以运行&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;D:\blog\bbs-web-mobile&lt;/code&gt;下运行&lt;code&gt;npm run dev&lt;/code&gt;如果出现类似于&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;  vite v2.9.15 dev server running at:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &amp;gt; Local: http://localhost:3000/admin/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  &amp;gt; Network: use `--host` to expose&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  ready in 579ms.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;并且无报错信息，默认可以运行&lt;/p&gt;
&lt;p&gt;admin 端和 pc 端同理&lt;/p&gt;
&lt;h3&gt;打包&lt;a href=&quot;#打包&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在&lt;code&gt;D:\blog&lt;/code&gt;下运行&lt;code&gt;mvn clean package&lt;/code&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;实际上 &lt;code&gt;mvn install&lt;/code&gt; 命令就包含了打包&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在&lt;code&gt;D:\blog\bbs-web-mobile&lt;/code&gt;下运行&lt;code&gt;npm run build&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;D:\blog\bbs-web-admin&lt;/code&gt;下运行&lt;code&gt;npm run build&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;D:\blog\bbs-web-pc&lt;/code&gt;下运行&lt;code&gt;npm run build&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;上传&lt;a href=&quot;#上传&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;这里以 Ubuntu 24.04 为例&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;将 &lt;code&gt;D:\blog\target\bbs-pro-6.9.jar&lt;/code&gt; 拷贝到服务器的&lt;code&gt;~&lt;/code&gt;下&lt;/p&gt;
&lt;p&gt;将 &lt;code&gt;D:\blog\bbs-web-pc\dist&lt;/code&gt;拷贝到服务器的&lt;code&gt;~/bbs-web-pc&lt;/code&gt;下&lt;/p&gt;
&lt;p&gt;将 &lt;code&gt;D:\blog\bbs-web-mobile\dist&lt;/code&gt;拷贝到服务器的&lt;code&gt;~/bbs-web-mobile&lt;/code&gt;下&lt;/p&gt;
&lt;p&gt;将 &lt;code&gt;D:\blog\bbs-web-admin\dist&lt;/code&gt;拷贝到服务器的&lt;code&gt;~/bbs-web-admin&lt;/code&gt;下&lt;/p&gt;
&lt;p&gt;将 &lt;code&gt;D:\blog\docker-compose.yml&lt;/code&gt;拷贝到服务器的&lt;code&gt;~&lt;/code&gt;下&lt;/p&gt;
&lt;p&gt;将 &lt;code&gt;D:\blog\nginx.conf&lt;/code&gt;拷贝到服务器的&lt;code&gt;~&lt;/code&gt;下&lt;/p&gt;
&lt;p&gt;将 &lt;code&gt;D:\blog\bbs-pro.sql&lt;/code&gt;拷贝到服务器的&lt;code&gt;~&lt;/code&gt;下&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192215473.png&quot; alt=&quot;image-20260731182223230&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731182223230&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;服务器环境搭建&lt;a href=&quot;#服务器环境搭建&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;安装 Docker&lt;a href=&quot;#安装-docker&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;参考&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://developer.aliyun.com/mirror/docker-ce&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://img.alicdn.com/tfs/TB1_ZXuNcfpK1RjSZFOXXa6nFXa-32-32.ico&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;developer.aliyun.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;docker-ce镜像_docker-ce下载地址_docker-ce安装教程-阿里巴巴开源镜像站&lt;/h3&gt;
        &lt;p&gt;阿里巴巴开源镜像站为您提供免费的docker-ce下载地址及docker-ce安装教程，docker-ce镜像简介：docker ce阿里巴巴开源镜像站&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://developer.aliyun.com/mirror/docker-ce&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://img.alicdn.com/tfs/TB1zLW7lFT7gK0jSZFpXXaTkpXa-292-292.png&quot; alt=&quot;docker-ce镜像_docker-ce下载地址_docker-ce安装教程-阿里巴巴开源镜像站&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;自动安装脚本为&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;curl&lt;/span&gt;&lt;span&gt; -fsSL&lt;/span&gt;&lt;span&gt; https://get.docker.com&lt;/span&gt;&lt;span&gt; |&lt;/span&gt;&lt;span&gt; bash&lt;/span&gt;&lt;span&gt; -s&lt;/span&gt;&lt;span&gt; docker&lt;/span&gt;&lt;span&gt; --mirror&lt;/span&gt;&lt;span&gt; Aliyun&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;添加用户组&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; groupadd&lt;/span&gt;&lt;span&gt; docker&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; usermod&lt;/span&gt;&lt;span&gt; -aG&lt;/span&gt;&lt;span&gt; docker&lt;/span&gt;&lt;span&gt; $USER&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;配置&lt;a href=&quot;#配置-2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;推荐使用轩辕镜像修改 docker 的配置&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;bash&lt;/span&gt;&lt;span&gt; &amp;lt;(&lt;/span&gt;&lt;span&gt;wget&lt;/span&gt;&lt;span&gt; -qO-&lt;/span&gt;&lt;span&gt; https://xuanyuan.cloud/docker.sh)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;运行&lt;a href=&quot;#运行&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;在 &lt;code&gt;~&lt;/code&gt; 下运行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;sudo&lt;/span&gt;&lt;span&gt; docker&lt;/span&gt;&lt;span&gt; compose&lt;/span&gt;&lt;span&gt; up&lt;/span&gt;&lt;span&gt; -d&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;修改论坛配置&lt;a href=&quot;#修改论坛配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;访问 &lt;code&gt;http://ip地址:8085/admin/login&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;用户名：admin&lt;/p&gt;
&lt;p&gt;密码：1234567&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731192218312.png&quot; alt=&quot;image-20260731190533587&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-20260731190533587&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;相关说明&lt;a href=&quot;#相关说明&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;相关 url&lt;a href=&quot;#相关-url&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;首页 &lt;code&gt;http://ip地址/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;后台 &lt;code&gt;http://ip地址/admin/login&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;logo 路径&lt;a href=&quot;#logo-路径&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;bbs-web-admin\public\favicon.ico&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bbs-web-pc\public\favicon.ico&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bbs-web-mobile\public\favicon.ico&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bbs-web-admin\src\assets\images\favicon.ico&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bbs-web-pc\src\assets\images\favicon.ico&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bbs-web-mobile\src\assets\images\favicon.ico&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bbs-web-admin\src\assets\images\logo.gif&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bbs-web-pc\src\assets\images\logo.gif&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bbs-web-mobile\src\assets\images\logo.gif&lt;/code&gt;&lt;/p&gt;</content:encoded><category>category:实验室</category><category>tag:技术文档</category></item><item><title>Markdown 增强语法</title><link>https://blog.hoshiumi.xyz/post/tech/markdown-zeng-qiang-yu-fa</link><guid isPermaLink="false">tech/markdown-zeng-qiang-yu-fa</guid><description>Markdown 增强
语法支持

GitHub Flavored Markdown (GFM)

表格
任务列表
删除线
自动链接



Mermaid 图表
支持在 Markdown 中使用 Mermaid 语法绘制流程图、时序图、架构图等。
```mermaid
flowchart LR</description><pubDate>Fri, 31 Jul 2026 03:15:19 GMT</pubDate><content:encoded>&lt;h1&gt;Markdown 增强&lt;a href=&quot;#markdown-增强&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;语法支持&lt;a href=&quot;#语法支持&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;GitHub Flavored Markdown (GFM)
&lt;ul&gt;
&lt;li&gt;表格&lt;/li&gt;
&lt;li&gt;任务列表&lt;/li&gt;
&lt;li&gt;删除线&lt;/li&gt;
&lt;li&gt;自动链接&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Mermaid 图表&lt;a href=&quot;#mermaid-图表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;支持在 Markdown 中使用 Mermaid 语法绘制流程图、时序图、架构图等。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;```mermaid&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;flowchart LR&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    A[构建时脚本] --&amp;gt; B[JSON 数据文件] --&amp;gt; C[运行时工具函数]&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;flowchart LR
    A[构建时脚本] --&amp;gt; B[JSON 数据文件] --&amp;gt; C[运行时工具函数]&lt;/pre&gt;
&lt;p&gt;支持的图表类型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;flowchart&lt;/code&gt; / &lt;code&gt;graph&lt;/code&gt; - 流程图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sequenceDiagram&lt;/code&gt; - 时序图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;classDiagram&lt;/code&gt; - 类图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stateDiagram&lt;/code&gt; - 状态图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;erDiagram&lt;/code&gt; - ER 图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gantt&lt;/code&gt; - 甘特图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pie&lt;/code&gt; - 饼图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mindmap&lt;/code&gt; - 思维导图&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;图表会自动跟随深色/浅色主题切换。更多语法参考 &lt;a href=&quot;https://mermaid.js.org/&quot;&gt;Mermaid 官方文档&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;Infographic 信息图&lt;a href=&quot;#infographic-信息图&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;支持使用 &lt;a href=&quot;https://infographic.antv.vision/&quot;&gt;@antv/infographic&lt;/a&gt; 在 Markdown 中绘制精美的信息图表，适合展示流程、对比、层级、统计等数据。&lt;/p&gt;
&lt;p&gt;使用方式：在代码块中使用 &lt;code&gt;infographic&lt;/code&gt; 标记，第一行指定模板名称，然后使用类似 YAML 的语法定义数据：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;```infographic&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;infographic list-grid-badge-card&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  title 技术栈&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  desc 我的常用技术栈&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  items&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - label TypeScript&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      desc 类型安全的 JavaScript&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      icon mdi/language-typescript&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - label React&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      desc 用户界面库&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      icon mdi/react&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - label Astro&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      desc 现代化静态站点生成器&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      icon mdi/rocket-launch&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;infographic list-grid-badge-card&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  title 技术栈&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  desc 我的常用技术栈&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  items&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - label TypeScript&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      desc 类型安全的 JavaScript&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      icon mdi/language-typescript&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - label React&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      desc 用户界面库&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      icon mdi/react&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - label Astro&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      desc 现代化静态站点生成器&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      icon mdi/rocket-launch&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;可用模板类型：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;列表类&lt;/strong&gt; (&lt;code&gt;list-*&lt;/code&gt;)：展示信息列表&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;list-grid-badge-card&lt;/code&gt; - 卡片网格布局&lt;/li&gt;
&lt;li&gt;&lt;code&gt;list-grid-candy-card-lite&lt;/code&gt; - 糖果风格卡片&lt;/li&gt;
&lt;li&gt;&lt;code&gt;list-row-horizontal-icon-arrow&lt;/code&gt; - 水平图标箭头列表&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;流程/顺序类&lt;/strong&gt; (&lt;code&gt;sequence-*&lt;/code&gt;)：展示步骤、流程或阶段&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;sequence-zigzag-steps-underline-text&lt;/code&gt; - 之字形步骤&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sequence-circular-simple&lt;/code&gt; - 圆形流程&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sequence-roadmap-vertical-simple&lt;/code&gt; - 垂直路线图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sequence-pyramid-simple&lt;/code&gt; - 金字塔结构&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;对比类&lt;/strong&gt; (&lt;code&gt;compare-*&lt;/code&gt;)：二元或多元对比&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;compare-binary-horizontal-simple-fold&lt;/code&gt; - 水平二元对比&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compare-swot&lt;/code&gt; - SWOT 分析&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compare-hierarchy-left-right-circle-node-pill-badge&lt;/code&gt; - 层级左右对比&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;层级类&lt;/strong&gt; (&lt;code&gt;hierarchy-*&lt;/code&gt;)：展示树形结构&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;hierarchy-tree-tech-style-capsule-item&lt;/code&gt; - 科技风格树形图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hierarchy-tree-curved-line-rounded-rect-node&lt;/code&gt; - 曲线连接树形图&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;图表类&lt;/strong&gt; (&lt;code&gt;chart-*&lt;/code&gt;)：数据可视化&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;chart-column-simple&lt;/code&gt; - 柱状图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chart-bar-plain-text&lt;/code&gt; - 条形图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chart-pie-plain-text&lt;/code&gt; - 饼图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;chart-line-plain-text&lt;/code&gt; - 折线图&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;其他&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;quadrant-*&lt;/code&gt; - 象限分析图&lt;/li&gt;
&lt;li&gt;&lt;code&gt;relation-*&lt;/code&gt; - 关系图&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;数据字段说明：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;title&lt;/code&gt; - 标题（可选）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;desc&lt;/code&gt; - 描述文本（可选）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;items&lt;/code&gt; - 条目数组，每个条目可包含：
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;label&lt;/code&gt; - 主标签文本&lt;/li&gt;
&lt;li&gt;&lt;code&gt;value&lt;/code&gt; - 数值（用于图表类模板）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;desc&lt;/code&gt; - 描述文本&lt;/li&gt;
&lt;li&gt;&lt;code&gt;icon&lt;/code&gt; - 图标名称（格式：&lt;code&gt;mdi/icon-name&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;children&lt;/code&gt; - 子条目（用于层级结构）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;主题定制：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;可以在数据后添加 &lt;code&gt;theme&lt;/code&gt; 块自定义颜色：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;```infographic&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;infographic sequence-pyramid-simple&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  items&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - label 基础层&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - label 中间层&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - label 顶层&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;theme&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  palette&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - #3b82f6&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - #8b5cf6&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - #f97316&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;信息图会自动跟随深色/浅色主题切换，并使用项目的寒蝉全圆体字体渲染。更多模板和语法参考 &lt;a href=&quot;https://infographic.antv.vision/&quot;&gt;Infographic 官方文档&lt;/a&gt;。&lt;/p&gt;
&lt;h2&gt;代码高亮&lt;a href=&quot;#代码高亮&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;基于 Shiki&lt;/li&gt;
&lt;li&gt;支持双主题（深色/浅色）&lt;/li&gt;
&lt;li&gt;支持语言标注&lt;/li&gt;
&lt;li&gt;行号显示&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;```javascript&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;function hello() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  console.log(&quot;Hello, world!&quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt; hello&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Hello, world!&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;标题自动链接&lt;a href=&quot;#标题自动链接&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;所有标题自动生成可点击的锚点链接。&lt;/p&gt;
&lt;h2&gt;链接自动嵌入&lt;a href=&quot;#链接自动嵌入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;独行的特殊链接会自动转换为嵌入组件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Twitter/X 链接&lt;/strong&gt;：自动嵌入 Tweet 组件&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CodePen 链接&lt;/strong&gt;：自动嵌入交互式 CodePen 演示&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;其他链接&lt;/strong&gt;：显示 OG 预览卡片（包含标题、描述、图片等）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 独行链接会被嵌入 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;https://x.com/vercel_dev/status/1997059920936775706&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;https://codepen.io/botteu/pen/YPKBrJX/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;https://github.com/vercel/react-tweet&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;反爬严格，获取不到元信息的链接&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;https://zhuanlan.zhihu.com/p/1900483903984243480&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 段落中的链接保持不变 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;这是一个 [&lt;/span&gt;&lt;span&gt;普通链接&lt;/span&gt;&lt;span&gt;](&lt;/span&gt;&lt;span&gt;https://example.com&lt;/span&gt;&lt;span&gt;)，不会被嵌入。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;
  &lt;span&gt;See the Pen &lt;a href=&quot;https://codepen.io/botteu/pen/YPKBrJX/&quot;&gt;YPKBrJX&lt;/a&gt; by botteu (&lt;a href=&quot;https://codepen.io/botteu&quot;&gt;@botteu&lt;/a&gt;) on &lt;a href=&quot;https://codepen.io&quot;&gt;CodePen&lt;/a&gt;.&lt;/span&gt;
&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://github.com/vercel/react-tweet&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          &lt;img src=&quot;https://github.com/fluidicon.png&quot; alt=&quot;&quot; loading=&quot;lazy&quot; /&gt;
          &lt;span&gt;github.com&lt;/span&gt;
        &lt;/div&gt;
        &lt;h3&gt;GitHub - vercel/react-tweet: Embed tweets in your React application.&lt;/h3&gt;
        &lt;p&gt;Embed tweets in your React application. Contribute to vercel/react-tweet development by creating an account on GitHub.&lt;/p&gt;
        &lt;div&gt;
          &lt;span&gt;https://github.com/vercel/react-tweet&lt;/span&gt;
           
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;div&gt;&lt;img src=&quot;https://opengraph.githubassets.com/630d415d01facac551f81a327677da29cff050886494351f2800de99bd07f8ed/vercel/react-tweet&quot; alt=&quot;GitHub - vercel/react-tweet: Embed tweets in your React application.&quot; loading=&quot;lazy&quot; /&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;反爬严格，获取不到元信息的链接&lt;/p&gt;
&lt;div&gt;
  &lt;a href=&quot;https://zhuanlan.zhihu.com/p/1900483903984243480&quot; target=&quot;_blank&quot;&gt;
    &lt;div&gt;
      &lt;div&gt;
        &lt;div&gt;
          
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;https://zhuanlan.zhihu.com/p/1900483903984243480&lt;/div&gt;
          &lt;div&gt;zhuanlan.zhihu.com&lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      
        
      
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;

&lt;p&gt;这是一个 &lt;a href=&quot;https://example.com&quot;&gt;普通链接&lt;/a&gt;，不会被嵌入。&lt;/p&gt;
&lt;h2&gt;Shoka 兼容 Markdown 语法&lt;a href=&quot;#shoka-兼容-markdown-语法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;astro-koharu 从 Hexo Shoka 主题迁移了一套丰富的 Markdown 扩展语法，所有功能均可通过 &lt;code&gt;config/site.yaml&lt;/code&gt; 的 &lt;code&gt;content&lt;/code&gt; 配置项独立开关。&lt;/p&gt;
&lt;h3&gt;文字特效（&lt;code&gt;enableShokaEffects&lt;/code&gt;）&lt;a href=&quot;#文字特效enableshokaeffects&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;支持多种行内文字装饰效果：&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;语法&lt;/th&gt;&lt;th&gt;效果&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;++文字++&lt;/code&gt;&lt;/td&gt;&lt;td&gt;下划线&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;lt;ins&amp;gt;&lt;/code&gt; 标签&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;++文字++{.wavy}&lt;/code&gt;&lt;/td&gt;&lt;td&gt;波浪下划线&lt;/td&gt;&lt;td&gt;支持 &lt;code&gt;.wavy&lt;/code&gt; 修饰符&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;++文字++{.dot}&lt;/code&gt;&lt;/td&gt;&lt;td&gt;着重点&lt;/td&gt;&lt;td&gt;支持 &lt;code&gt;.dot&lt;/code&gt; 修饰符&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;++文字++{.primary}&lt;/code&gt;&lt;/td&gt;&lt;td&gt;彩色下划线&lt;/td&gt;&lt;td&gt;支持 &lt;code&gt;.primary&lt;/code&gt; &lt;code&gt;.success&lt;/code&gt; &lt;code&gt;.warning&lt;/code&gt; &lt;code&gt;.danger&lt;/code&gt; &lt;code&gt;.info&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;==文字==&lt;/code&gt;&lt;/td&gt;&lt;td&gt;高亮&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;lt;mark&amp;gt;&lt;/code&gt; 标签&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;~文字~&lt;/code&gt;&lt;/td&gt;&lt;td&gt;下标&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;lt;sub&amp;gt;&lt;/code&gt; 标签，如 H&lt;sub&gt;2&lt;/sub&gt;O&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;^文字^&lt;/code&gt;&lt;/td&gt;&lt;td&gt;上标&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;lt;sup&amp;gt;&lt;/code&gt; 标签，如 E=mc&lt;sup&gt;2&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;p&gt;这是下划线文字 波浪下划线 着重点标记&lt;/p&gt;
&lt;p&gt;主色调 成功 警告 危险 信息&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;这是高亮文字&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;H&lt;sub&gt;2&lt;/sub&gt;O 是水的化学式，E = mc&lt;sup&gt;2&lt;/sup&gt; 是质能方程&lt;/p&gt;
&lt;h3&gt;颜色文字与特殊样式（&lt;code&gt;enableShokaAttrs&lt;/code&gt;）&lt;a href=&quot;#颜色文字与特殊样式enableshokaattrs&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;&lt;span&gt;文字&lt;/span&gt;&lt;/code&gt; 语法为文字添加颜色和样式：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;红色&lt;/span&gt;&lt;span&gt;]{.red} [&lt;/span&gt;&lt;span&gt;粉色&lt;/span&gt;&lt;span&gt;]{.pink} [&lt;/span&gt;&lt;span&gt;橙色&lt;/span&gt;&lt;span&gt;]{.orange} [&lt;/span&gt;&lt;span&gt;黄色&lt;/span&gt;&lt;span&gt;]{.yellow}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;绿色&lt;/span&gt;&lt;span&gt;]{.green} [&lt;/span&gt;&lt;span&gt;水色&lt;/span&gt;&lt;span&gt;]{.aqua} [&lt;/span&gt;&lt;span&gt;蓝色&lt;/span&gt;&lt;span&gt;]{.blue} [&lt;/span&gt;&lt;span&gt;紫色&lt;/span&gt;&lt;span&gt;]{.purple} [&lt;/span&gt;&lt;span&gt;灰色&lt;/span&gt;&lt;span&gt;]{.grey}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;这段文字会有彩虹渐变效果&lt;/span&gt;&lt;span&gt;]{.rainbow}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;Ctrl&lt;/span&gt;&lt;span&gt;]{.kbd} + [&lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;]{.kbd} 复制，[&lt;/span&gt;&lt;span&gt;Ctrl&lt;/span&gt;&lt;span&gt;]{.kbd} + [&lt;/span&gt;&lt;span&gt;V&lt;/span&gt;&lt;span&gt;]{.kbd} 粘贴&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;默认&lt;/span&gt;&lt;span&gt;]{.label .default} [&lt;/span&gt;&lt;span&gt;主要&lt;/span&gt;&lt;span&gt;]{.label .primary} [&lt;/span&gt;&lt;span&gt;信息&lt;/span&gt;&lt;span&gt;]{.label .info}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;成功&lt;/span&gt;&lt;span&gt;]{.label .success} [&lt;/span&gt;&lt;span&gt;警告&lt;/span&gt;&lt;span&gt;]{.label .warning} [&lt;/span&gt;&lt;span&gt;危险&lt;/span&gt;&lt;span&gt;]{.label .danger}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;p&gt;&lt;span&gt;红色&lt;/span&gt; &lt;span&gt;粉色&lt;/span&gt; &lt;span&gt;橙色&lt;/span&gt; &lt;span&gt;黄色&lt;/span&gt; &lt;span&gt;绿色&lt;/span&gt; &lt;span&gt;水色&lt;/span&gt; &lt;span&gt;蓝色&lt;/span&gt; &lt;span&gt;紫色&lt;/span&gt; &lt;span&gt;灰色&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;这段文字会有彩虹渐变效果&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Ctrl&lt;/span&gt; + &lt;span&gt;C&lt;/span&gt; 复制，&lt;span&gt;Ctrl&lt;/span&gt; + &lt;span&gt;V&lt;/span&gt; 粘贴&lt;/p&gt;
&lt;p&gt;&lt;span&gt;默认&lt;/span&gt; &lt;span&gt;主要&lt;/span&gt; &lt;span&gt;信息&lt;/span&gt; &lt;span&gt;成功&lt;/span&gt; &lt;span&gt;警告&lt;/span&gt; &lt;span&gt;危险&lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;隐藏文字 / Spoiler（&lt;code&gt;enableShokaSpoiler&lt;/code&gt;）&lt;a href=&quot;#隐藏文字--spoilerenableshokaspoiler&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;这里有一段!!隐藏文字，点击显示!!&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;这里有一段!!模糊文字，鼠标悬停显示!!{.blur}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;p&gt;这里有一段隐藏文字，点击显示&lt;/p&gt;
&lt;p&gt;这里有一段&lt;span&gt;模糊文字，鼠标悬停显示&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;默认模式：点击后粒子消散动画揭示文字（基于 spoilerjs Web Component）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.blur&lt;/code&gt; 模式：鼠标悬停时模糊消失&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;注音标注 / Ruby（&lt;code&gt;enableShokaRuby&lt;/code&gt;）&lt;a href=&quot;#注音标注--rubyenableshokaruby&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;为 CJK 文字添加注音，适用于日语假名、汉语拼音等：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{漢字^かんじ}的注音示例&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;{取り返す^とりかえす}是日语中&quot;取回&quot;的意思&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;p&gt;{漢字&lt;sup&gt;かんじ}的注音示例。{取り返す&lt;/sup&gt;とりかえす}是日语中&quot;取回&quot;的意思。&lt;/p&gt;
&lt;p&gt;渲染为 HTML &lt;code&gt;&amp;lt;ruby&amp;gt;&lt;/code&gt; 标签，浏览器原生支持。&lt;/p&gt;
&lt;h3&gt;提醒块 / Note Blocks（&lt;code&gt;enableShokaContainers&lt;/code&gt;）&lt;a href=&quot;#提醒块--note-blocksenableshokacontainers&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;:::&lt;/code&gt; 语法创建不同样式的提醒块：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;:::default&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;这是默认提醒块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::primary&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;这是主要提醒块，用于重要提示&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::info&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;这是信息提醒块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::success&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;这是成功提醒块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::warning&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;这是警告提醒块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::danger&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;这是危险提醒块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::info no-icon&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;这是没有图标的信息块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;div&gt;
&lt;p&gt;这是信息提醒块，用于提供额外信息&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;这是警告提醒块，请注意&lt;/p&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;p&gt;这是危险提醒块，务必谨慎&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;支持的样式：&lt;code&gt;default&lt;/code&gt;、&lt;code&gt;primary&lt;/code&gt;、&lt;code&gt;info&lt;/code&gt;、&lt;code&gt;success&lt;/code&gt;、&lt;code&gt;warning&lt;/code&gt;、&lt;code&gt;danger&lt;/code&gt;。添加 &lt;code&gt;no-icon&lt;/code&gt; 可隐藏图标。提醒块内部支持嵌套 Markdown 语法。&lt;/p&gt;
&lt;h3&gt;折叠块 / Collapse（&lt;code&gt;enableShokaContainers&lt;/code&gt;）&lt;a href=&quot;#折叠块--collapseenableshokacontainers&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;+++&lt;/code&gt; 语法创建可折叠内容（渲染为 &lt;code&gt;&amp;lt;details&amp;gt;&lt;/code&gt; + &lt;code&gt;&amp;lt;summary&amp;gt;&lt;/code&gt;）：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;+++primary 点击展开详细内容&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;折叠的内容，支持 &lt;/span&gt;&lt;span&gt;**Markdown**&lt;/span&gt;&lt;span&gt; 格式化。&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; 列表项 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; 列表项 2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;+++&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;+++warning 注意事项&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;需要注意的内容&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;+++&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;+++danger 危险操作&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;请确保你知道自己在做什么！&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;+++&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;示例效果：&lt;/p&gt;

点击展开详细内容
&lt;div&gt;
&lt;p&gt;折叠的内容，支持 &lt;strong&gt;Markdown&lt;/strong&gt; 格式化。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;列表项 1&lt;/li&gt;
&lt;li&gt;列表项 2&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;


注意事项
&lt;div&gt;
&lt;p&gt;需要注意的内容&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;支持的样式：&lt;code&gt;primary&lt;/code&gt;、&lt;code&gt;info&lt;/code&gt;、&lt;code&gt;success&lt;/code&gt;、&lt;code&gt;warning&lt;/code&gt;、&lt;code&gt;danger&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;标签卡 / Tabs（&lt;code&gt;enableShokaContainers&lt;/code&gt;）&lt;a href=&quot;#标签卡--tabsenableshokacontainers&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;;;;&lt;/code&gt; 语法创建标签页切换，同一组 ID 的标签卡会自动组合：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;;;;mygroup JavaScript&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```js&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Hello, World!&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;;;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;;;;mygroup Python&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```python&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;print(&apos;Hello, World!&apos;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;;;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;;;;mygroup Rust&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```rust&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;fn main() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    println!(&quot;Hello, World!&quot;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;;;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
JavaScript
Python
Rust
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Hello, World!&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;print&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&apos;Hello, World!&apos;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;fn&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Hello, World!&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;;;;groupId 标签名&lt;/code&gt; 定义一个标签页，同一 &lt;code&gt;groupId&lt;/code&gt; 的标签自动组合&lt;/li&gt;
&lt;li&gt;第一个标签默认激活&lt;/li&gt;
&lt;li&gt;标签内支持任意 Markdown 内容&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;友链卡片（&lt;code&gt;enableShokaHexoTags&lt;/code&gt;）&lt;a href=&quot;#友链卡片enableshokahexotags&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;{% links %}&lt;/code&gt; 标签在文章中插入友链卡片网格：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{% links %}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; site: 博客名称&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  url: https://example.com&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  owner: 站长昵称&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  desc: 站点描述&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  image: https://example.com/avatar.png&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  color: &apos;#ed788b&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; site: 另一个博客&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  url: https://example2.com&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  owner: Alice&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  desc: 一个热爱技术的博客&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  image: https://api.dicebear.com/7.x/avataaars/svg?seed=Alice&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  color: &apos;#BEDCFF&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;{% endlinks %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;div&gt;
&lt;a href=&quot;https://blog.cosine.ren&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.cosine.ren/img/avatar.webp&quot; alt=&quot;余弦の博客&quot; loading=&quot;lazy&quot; /&gt;&lt;div&gt;&lt;div&gt;余弦の博客&lt;/div&gt;&lt;div&gt;FE / ACG / 手工&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;
&lt;a href=&quot;https://example.com&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://api.dicebear.com/7.x/avataaars/svg?seed=Alice&quot; alt=&quot;示例博客&quot; loading=&quot;lazy&quot; /&gt;&lt;div&gt;&lt;div&gt;示例博客&lt;/div&gt;&lt;div&gt;一个热爱技术的博客&lt;/div&gt;&lt;/div&gt;&lt;/a&gt;
&lt;/div&gt;
&lt;p&gt;卡片数据使用 YAML 格式，支持 &lt;code&gt;site&lt;/code&gt;、&lt;code&gt;url&lt;/code&gt;、&lt;code&gt;owner&lt;/code&gt;、&lt;code&gt;desc&lt;/code&gt;、&lt;code&gt;image&lt;/code&gt;、&lt;code&gt;color&lt;/code&gt; 字段。&lt;/p&gt;
&lt;h3&gt;音频播放器（&lt;code&gt;enableShokaHexoTags&lt;/code&gt;）&lt;a href=&quot;#音频播放器enableshokahexotags&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;{% media audio %}&lt;/code&gt; 标签嵌入音频播放器，支持网易云音乐、QQ 音乐等平台（通过 &lt;a href=&quot;https://github.com/metowolf/meting&quot;&gt;Meting&lt;/a&gt; API 解析）。&lt;/p&gt;
&lt;p&gt;默认使用 &lt;code&gt;https://163.hyc.moe/&lt;/code&gt; 作为 Meting API，可在 &lt;code&gt;config/site.yaml&lt;/code&gt; 的 &lt;code&gt;bgm.metingApi&lt;/code&gt; 中自定义，推荐自部署以获得更稳定的服务。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{% media audio %}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; name: 歌曲名称&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  url: https://music.163.com/#/song?id=3339210292&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;{% endmedia %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;支持歌单模式，可配置多个分组：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{% media audio %}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; title: 歌单名称 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  list:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    -&lt;/span&gt;&lt;span&gt; https://music.163.com/#/playlist?id=8676645748&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; title: 歌单名称 2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  list:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    -&lt;/span&gt;&lt;span&gt; https://music.163.com/#/playlist?id=17606384886&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;{% endmedia %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;/div&gt;
&lt;h3&gt;视频播放器（&lt;code&gt;enableShokaHexoTags&lt;/code&gt;）&lt;a href=&quot;#视频播放器enableshokahexotags&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;{% media video %}&lt;/code&gt; 标签嵌入视频播放器：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;{% media video %}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; name: 视频 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  url: https://example.com/video1.mp4&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; name: 视频 2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  url: https://example.com/video2.mp4&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;{% endmedia %}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;/div&gt;
&lt;p&gt;多个视频时自动显示播放列表。&lt;/p&gt;
&lt;h3&gt;练习题系统（&lt;code&gt;enableQuiz&lt;/code&gt;）&lt;a href=&quot;#练习题系统enablequiz&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;支持四种交互式题型，适合教程和学习笔记。需在文章 frontmatter 中设置 &lt;code&gt;quiz: true&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;单选题：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; 下列哪个是 JavaScript 的基本数据类型？{.quiz}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span&gt; Object{.options}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span&gt; Array{.options}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span&gt; Symbol{.correct}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span&gt; Function{.options}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;gt; 解析：Symbol 是 ES6 引入的基本数据类型。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;下列哪个是 JavaScript 的基本数据类型？
&lt;ul&gt;
&lt;li&gt;Object&lt;/li&gt;
&lt;li&gt;Array&lt;/li&gt;
&lt;li&gt;Symbol&lt;/li&gt;
&lt;li&gt;Function&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;解析：Symbol 是 ES6 引入的基本数据类型，而 Object、Array、Function 都是引用类型。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;选项标记 &lt;code&gt;&lt;/code&gt; 为正确答案，&lt;code&gt;{.options}&lt;/code&gt; 为干扰项&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;多选题：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; 以下哪些是 CSS 布局方式？{.quiz .multi}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span&gt; Flexbox{.correct}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span&gt; jQuery{.options}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span&gt; Grid{.correct}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  -&lt;/span&gt;&lt;span&gt; Float{.correct}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;gt; 解析：Flexbox、Grid 和 Float 都是 CSS 布局方式。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;以下哪些是 CSS 布局方式？
&lt;ul&gt;
&lt;li&gt;Flexbox&lt;/li&gt;
&lt;li&gt;jQuery&lt;/li&gt;
&lt;li&gt;Grid&lt;/li&gt;
&lt;li&gt;Float&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;解析：Flexbox、Grid 和 Float 都是 CSS 布局方式。jQuery 是一个 JavaScript 库。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;添加 &lt;code&gt;.multi&lt;/code&gt; 标记启用多选模式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;判断题：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; `const`&lt;/span&gt;&lt;span&gt; 声明的变量不能重新赋值，但可以修改其属性。{.quiz .true}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;gt; 解析：&lt;/span&gt;&lt;span&gt;`const`&lt;/span&gt;&lt;span&gt; 只保证变量绑定不可变。&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; HTML 是一种编程语言。{.quiz}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;gt; 解析：HTML 是标记语言，不是编程语言。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;const&lt;/code&gt; 声明的变量不能重新赋值，但可以修改其属性。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;解析：&lt;code&gt;const&lt;/code&gt; 只保证变量绑定不可变，如果变量指向一个对象，其属性仍然可以修改。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;HTML 是一种编程语言。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;解析：HTML（超文本标记语言）是一种标记语言，不是编程语言。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;添加 &lt;code&gt;.true&lt;/code&gt; 表示陈述正确，不添加 &lt;code&gt;.true&lt;/code&gt; 则表示错误&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;填空题：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; CSS 中，[&lt;/span&gt;&lt;span&gt;Flexbox&lt;/span&gt;&lt;span&gt;]{.gap} 适合一维布局，[&lt;/span&gt;&lt;span&gt;Grid&lt;/span&gt;&lt;span&gt;]{.gap} 适合二维布局。{.quiz .fill}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;gt; 常见错误：[&lt;/span&gt;&lt;span&gt;Float&lt;/span&gt;&lt;span&gt;]{.mistake}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CSS 中，&lt;span&gt;Flexbox&lt;/span&gt; 适合一维布局，&lt;span&gt;Grid&lt;/span&gt; 适合二维布局。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;常见错误：&lt;span&gt;Float&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;[答案]&lt;/code&gt; 标记正确答案（支持多个空）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[错误答案]&lt;/code&gt; 标记常见错误（首次答错时提示）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;gt;&lt;/code&gt; 引用块内容为解析说明&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;数学公式（&lt;code&gt;enableMath&lt;/code&gt;）&lt;a href=&quot;#数学公式enablemath&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;基于 KaTeX 渲染数学公式。需在文章 frontmatter 中设置 &lt;code&gt;math: true&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;行内公式：$E = mc^2$&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;块级公式：&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;$$&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;$$&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;p&gt;行内公式：&lt;span&gt;&lt;span&gt;E=mc2E = mc^2&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;E&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;m&lt;/span&gt;&lt;span&gt;&lt;span&gt;c&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;块级公式：&lt;/p&gt;
&lt;span&gt;&lt;span&gt;&lt;span&gt;∑n=1∞1n2=π26\sum_{n=1}^{\infty} \frac{1}{n^2} = \frac{\pi^2}{6}&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;∑&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;∞&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;6&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;π&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;h3&gt;代码块增强（&lt;code&gt;enableCodeMeta&lt;/code&gt;）&lt;a href=&quot;#代码块增强enablecodemeta&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;代码块支持额外的元数据标注：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;```js title=&quot;hello.js&quot; url=&quot;https://example.com&quot; linkText=&quot;查看源码&quot; mark:1,3&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; greeting&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &apos;Hello&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &apos;World&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`${&lt;/span&gt;&lt;span&gt;greeting&lt;/span&gt;&lt;span&gt;}, ${&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;}!`&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```bash command:(&quot;$&quot;:1-3)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; astro&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; run&lt;/span&gt;&lt;span&gt; dev&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; run&lt;/span&gt;&lt;span&gt; build&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;```&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;元数据&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;title=&quot;文件名&quot;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;显示代码块标题&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;url=&quot;链接&quot;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;添加外部源码链接&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;linkText=&quot;文字&quot;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;自定义链接文字（默认为 URL）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;mark:1,3&lt;/code&gt;&lt;/td&gt;&lt;td&gt;高亮指定行&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;command:(&quot;$&quot;:1-3)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;标记 shell 命令行（显示 &lt;code&gt;$&lt;/code&gt; 前缀）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;示例效果：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; greeting&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &apos;Hello&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;const&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &apos;World&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;console.&lt;/span&gt;&lt;span&gt;log&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;`${&lt;/span&gt;&lt;span&gt;greeting&lt;/span&gt;&lt;span&gt;}, ${&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;}!`&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; astro&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; run&lt;/span&gt;&lt;span&gt; dev&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; run&lt;/span&gt;&lt;span&gt; build&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Shoka 功能配置总览：&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;所有 Shoka 兼容功能均可在 &lt;code&gt;config/site.yaml&lt;/code&gt; 的 &lt;code&gt;content&lt;/code&gt; 部分独立开关：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;content&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  # Shoka 兼容功能（默认全部启用，设为 false 可关闭）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enableShokaContainers&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;   # :::提醒块 ;;;标签卡 +++折叠块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enableShokaAttrs&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;        # &lt;span&gt;text&lt;/span&gt; 属性语法&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enableShokaEffects&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;      # ++下划线++ ==高亮== ~下标~ ^上标^&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enableShokaSpoiler&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;      # !!隐藏文字!!&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enableShokaRuby&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;         # {文字^注音} 注音标注&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enableShokaHexoTags&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;     # {% links %} {% media %} Hexo 标签&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enableMath&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;              # $数学公式$ KaTeX 渲染&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enableCodeMeta&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;          # 代码块增强 (title, mark, command)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enableQuiz&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;              # 练习题交互功能&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enableEncryptedBlock&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;    # :::encrypted{password=&quot;...&quot;} 加密内容块&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;内容加密（&lt;code&gt;enableEncryptedBlock&lt;/code&gt;）&lt;a href=&quot;#内容加密enableencryptedblock&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;博客支持两种加密方式，满足不同的内容保护需求：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. 加密块 —— 文章局部加密&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在文章中使用 &lt;code&gt;:::encrypted{password=&quot;...&quot;}&lt;/code&gt; 语法包裹需要加密的内容：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;这部分内容公开可见。&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::encrypted{password=&quot;demo&quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;这段内容需要输入密码 &quot;demo&quot; 才能查看。&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;支持完整的 Markdown 语法，包括代码块、列表、图片等。&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;:::&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;这部分也是公开的。&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;加密块适合在一篇文章中&lt;strong&gt;部分隐藏&lt;/strong&gt;敏感内容（如答案、剧透、私密笔记），其余内容正常展示。需要在 &lt;code&gt;config/site.yaml&lt;/code&gt; 中启用 &lt;code&gt;enableEncryptedBlock: true&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. 加密文章 —— 整篇文章加密&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在文章的 frontmatter 中添加 &lt;code&gt;password&lt;/code&gt; 字段即可加密整篇文章：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;我的私密文章&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;date&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;2026-01-01&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;password&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mySecretPassword&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;categories&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  - &lt;/span&gt;&lt;span&gt;笔记&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;这里的所有内容都会被加密...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;加密文章会显示一个全屏的解锁界面，输入正确密码后才能查看内容。解锁后代码高亮、目录导航、Mermaid 图表等增强功能会自动重新初始化。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;安全模型说明：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;加密功能使用 &lt;strong&gt;AES-256-GCM&lt;/strong&gt; 算法，安全模型如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;构建时加密&lt;/strong&gt;：密码仅在 &lt;code&gt;pnpm build&lt;/code&gt; 时用于加密，生成的 HTML 中&lt;strong&gt;不包含密码明文&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;客户端解密&lt;/strong&gt;：读者在浏览器中输入密码后，通过 Web Crypto API 在本地解密，密码不会发送到任何服务器&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;密钥派生&lt;/strong&gt;：使用 PBKDF2（100,000 次迭代）从密码派生加密密钥，提高暴力破解成本&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;搜索排除&lt;/strong&gt;：加密内容自动添加 &lt;code&gt;data-pagefind-ignore&lt;/code&gt;，不会被 Pagefind 搜索索引&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;注意&lt;/strong&gt;：此加密设计的主要目的是&lt;strong&gt;防止搜索引擎和爬虫索引加密内容&lt;/strong&gt;，而非抵御针对性攻击。密文和盐值嵌入在公开的 HTML 中，理论上可被离线暴力破解。请使用强密码，不要用于保护高度敏感的信息。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;加密文章的特殊行为：&lt;/strong&gt;&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方面&lt;/th&gt;&lt;th&gt;行为&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;RSS 订阅&lt;/td&gt;&lt;td&gt;标题前加 🔒 前缀，内容替换为&quot;此文章已加密&quot;提示&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;SEO / meta&lt;/td&gt;&lt;td&gt;description 使用 frontmatter 中的 &lt;code&gt;description&lt;/code&gt;（若未设置则显示通用加密提示）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;搜索索引&lt;/td&gt;&lt;td&gt;加密内容不会被 Pagefind 索引&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;目录导航&lt;/td&gt;&lt;td&gt;解锁前不显示，解锁后自动重建&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;AI 摘要&lt;/td&gt;&lt;td&gt;基于加密前的原文生成（构建时可访问明文）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;其他增强&lt;a href=&quot;#其他增强&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;自动目录生成&lt;/li&gt;
&lt;li&gt;阅读时间计算&lt;/li&gt;
&lt;li&gt;外部链接自动添加 &lt;code&gt;target=&quot;_blank&quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>category:技术</category><category>tag:Markdown</category><category>tag:Astro</category><category>tag:Mermaid</category><category>tag:Shoka</category><category>tag:技术文档</category></item><item><title>项目前端开发环境搭建</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/web/xiang-mu-qian-duan-kai-fa-huan-jing-da-jian</link><guid isPermaLink="false">learn/hyxy/web/xiang-mu-qian-duan-kai-fa-huan-jing-da-jian</guid><description>项目前端开发环境搭建
工具简介
Node.js
Node.js 是一个开源、跨平台的 JavaScript 运行时环境。它基于 Chrome 使用的 V8 引擎，使 JavaScript 可以在浏览器之外的 运行环境 中执行。
Node.js 不仅能用于开发 Web</description><pubDate>Fri, 31 Jul 2026 00:55:39 GMT</pubDate><content:encoded>&lt;h1&gt;项目前端开发环境搭建&lt;a href=&quot;#项目前端开发环境搭建&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;工具简介&lt;a href=&quot;#工具简介&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Node.js&lt;a href=&quot;#nodejs&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Node.js 是一个开源、跨平台的 JavaScript 运行时环境。它基于 &lt;a href=&quot;https://baike.baidu.com/item/Chrome/5633839?fromModule=lemma_inlink&quot;&gt;Chrome&lt;/a&gt; 使用的 &lt;a href=&quot;https://baike.baidu.com/item/V8/6178125?fromModule=lemma_inlink&quot;&gt;V8&lt;/a&gt; 引擎，使 &lt;a href=&quot;https://baike.baidu.com/item/JavaScript/321142?fromModule=lemma_inlink&quot;&gt;JavaScript&lt;/a&gt; 可以在浏览器之外的 &lt;a href=&quot;https://baike.baidu.com/item/%E8%BF%90%E8%A1%8C%E7%8E%AF%E5%A2%83/6555199?fromModule=lemma_inlink&quot;&gt;运行环境&lt;/a&gt; 中执行。&lt;/p&gt;
&lt;p&gt;Node.js 不仅能用于开发 Web 服务端程序，还可用于构建前端工程化工具、命令行工具、自动化脚本等。现代前端项目通常依赖 Node.js 来运行构建工具、安装依赖和启动开发服务器。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://baike.baidu.com/item/V8/6178125?fromModule=lemma_inlink&quot;&gt;V8&lt;/a&gt; 会使用即时编译等 &lt;a href=&quot;https://baike.baidu.com/item/%E7%BC%96%E8%AF%91%E6%8A%80%E6%9C%AF/9854683?fromModule=lemma_inlink&quot;&gt;编译技术&lt;/a&gt; 执行 JavaScript。相较于传统逐行解释的 &lt;a href=&quot;https://baike.baidu.com/item/%E8%84%9A%E6%9C%AC%E8%AF%AD%E8%A8%80/1379708?fromModule=lemma_inlink&quot;&gt;脚本语言&lt;/a&gt; 执行方式，这类优化能够提升代码的 &lt;a href=&quot;https://baike.baidu.com/item/%E8%BF%90%E8%A1%8C%E9%80%9F%E5%BA%A6/7917106?fromModule=lemma_inlink&quot;&gt;运行速度&lt;/a&gt;，并帮助团队降低重复搭建工具链带来的 &lt;a href=&quot;https://baike.baidu.com/item/%E5%BC%80%E5%8F%91%E6%88%90%E6%9C%AC/6160378?fromModule=lemma_inlink&quot;&gt;开发成本&lt;/a&gt;。&lt;/p&gt;
&lt;h3&gt;npm&lt;a href=&quot;#npm&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;npm 是 Node.js 生态中常用的包管理器。安装 Node.js 时通常会同时安装 npm，因此一般不需要单独安装。&lt;/p&gt;
&lt;p&gt;npm 既连接用于&lt;a href=&quot;https://www.baidu.com/s?rsv_idx=2&amp;amp;tn=68018901_16_pg&amp;amp;wd=%E5%9C%A8%E7%BA%BF%E6%8F%90%E4%BE%9B%E5%BC%80%E6%BA%90&amp;amp;usm=1&amp;amp;ie=utf-8&amp;amp;rsv_pq=99c29115000ad7d7&amp;amp;oq=npm%E4%BD%9C%E7%94%A8&amp;amp;rsv_t=8b32+cnjMkZxYAnH1bWpRjdQYeHzJp4jqHS0SFcAMjdhFAvgTPHkqTbNCrjj10/367V6lVo&amp;amp;rsv_dl=re_dqa_generate&amp;amp;sa=re_dqa_generate&quot;&gt;在线提供开源&lt;/a&gt; &lt;a href=&quot;https://www.baidu.com/s?rsv_idx=2&amp;amp;tn=68018901_16_pg&amp;amp;wd=Node.js&amp;amp;usm=1&amp;amp;ie=utf-8&amp;amp;rsv_pq=99c29115000ad7d7&amp;amp;oq=npm%E4%BD%9C%E7%94%A8&amp;amp;rsv_t=4c67xa5AePjCm5P4IsnEG7mUBZu1yQWnn34ufCLyeKxes5/p43D8Lj72s5rYvJXJFbVmU4c&amp;amp;rsv_dl=re_dqa_generate&amp;amp;sa=re_dqa_generate&quot;&gt;Node.js&lt;/a&gt; 软件包的注册表，也提供命令行工具，用于完成以下工作：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;根据 &lt;code&gt;package.json&lt;/code&gt; 安装和管理项目依赖。&lt;/li&gt;
&lt;li&gt;通过 &lt;code&gt;package-lock.json&lt;/code&gt; 锁定依赖解析结果，提高不同环境中的安装一致性。&lt;/li&gt;
&lt;li&gt;执行 &lt;code&gt;package.json&lt;/code&gt; 中定义的脚本，例如 &lt;code&gt;npm run dev&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;发布和维护 npm 软件包。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Yarn、pnpm 和 cnpm 都与 npm 生态有关，但它们的定位并不完全相同。Yarn 和 pnpm 是可选的包管理器，cnpm 是兼容 npm 使用方式的客户端。它们不应被简单理解为“npm 的国内镜像”。一个项目应尽量统一包管理器，并提交对应的锁文件，避免混用后产生依赖差异。&lt;/p&gt;
&lt;h3&gt;NVM for Windows&lt;a href=&quot;#nvm-for-windows&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;NVM for Windows 是 Windows 平台上的 Node.js 版本管理工具，可在同一台计算机上安装和切换多个 Node.js 版本。&lt;/p&gt;
&lt;p&gt;主要用途包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;安装、卸载和查看不同版本的 Node.js。&lt;/li&gt;
&lt;li&gt;根据项目要求切换 Node.js 版本。&lt;/li&gt;
&lt;li&gt;设置当前生效的 Node.js 版本。&lt;/li&gt;
&lt;li&gt;降低多个项目对不同 Node.js 版本的兼容成本。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：Windows 使用的是 NVM for Windows，它与 macOS、Linux 上常见的 &lt;code&gt;nvm&lt;/code&gt; 不是同一个项目，安装方式和部分命令存在差异。&lt;/p&gt;
&lt;h2&gt;安装方案说明&lt;a href=&quot;#安装方案说明&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;推荐使用 NVM for Windows 统一安装和管理 Node.js，不建议先安装独立版 Node.js，再安装 NVM for Windows。两套安装同时存在时，可能因环境变量或安装目录冲突，导致 &lt;code&gt;nvm use&lt;/code&gt; 切换后 &lt;code&gt;node -v&lt;/code&gt; 仍显示旧版本。&lt;/p&gt;
&lt;p&gt;本项目使用的 Node.js 版本为 &lt;code&gt;22.17.0&lt;/code&gt;。课程截图中还演示了 &lt;code&gt;14.20.0&lt;/code&gt;，该版本仅用于需要兼容旧项目时的版本切换练习，不应作为当前项目的默认版本。&lt;/p&gt;
&lt;h2&gt;清理旧环境&lt;a href=&quot;#清理旧环境&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;已经安装过 Node.js 或 NVM for Windows 时，建议先清理旧环境；全新电脑可跳过本节。&lt;/p&gt;
&lt;h3&gt;第一步：关闭相关程序&lt;a href=&quot;#第一步关闭相关程序&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;关闭正在使用 Node.js 的终端、IDE、开发服务器和其他相关进程，避免文件被占用。&lt;/p&gt;
&lt;h3&gt;第二步：记录当前环境&lt;a href=&quot;#第二步记录当前环境&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;打开命令提示符，执行以下命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;node&lt;/span&gt;&lt;span&gt; -v&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; -v&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; node&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt; npm&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;where&lt;/code&gt; 命令可以帮助确认系统实际调用的是哪个目录中的可执行文件。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731085602274.png&quot; alt=&quot;Node.js 和 npm 版本检查&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;Node.js 和 npm 版本检查&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;第三步：卸载旧版 Node.js&lt;a href=&quot;#第三步卸载旧版-nodejs&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 Windows 的“设置”或“控制面板”中卸载独立安装的 Node.js，然后检查原安装目录是否仍有残留。&lt;/p&gt;
&lt;p&gt;如果后续准备使用 NVM for Windows，尤其要确认原来的 Node.js 实体目录没有占用 NVM 的符号链接位置。删除目录前应先确认其中没有需要保留的配置或文件。&lt;/p&gt;
&lt;h3&gt;第四步：卸载旧版 NVM for Windows&lt;a href=&quot;#第四步卸载旧版-nvm-for-windows&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;需要重新安装 NVM for Windows 时，可通过 Windows 的应用卸载功能进行卸载。卸载后检查 &lt;code&gt;NVM_HOME&lt;/code&gt;、&lt;code&gt;NVM_SYMLINK&lt;/code&gt; 和 &lt;code&gt;PATH&lt;/code&gt; 中是否仍保留失效配置。&lt;/p&gt;
&lt;p&gt;不要直接删除不熟悉的环境变量。应先确认变量指向旧的 NVM 安装目录，再进行清理。&lt;/p&gt;
&lt;h3&gt;第五步：处理 npm 残留&lt;a href=&quot;#第五步处理-npm-残留&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;可先使用以下命令查看 npm 的缓存和全局安装目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; get&lt;/span&gt;&lt;span&gt; cache&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; config&lt;/span&gt;&lt;span&gt; get&lt;/span&gt;&lt;span&gt; prefix&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;确认不再需要旧环境后，再清理对应目录。用户目录中的 &lt;code&gt;.npmrc&lt;/code&gt; 可能包含镜像、代理或私有仓库配置，删除前应先备份。&lt;/p&gt;
&lt;h2&gt;安装 NVM for Windows&lt;a href=&quot;#安装-nvm-for-windows&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;第一步：运行安装程序&lt;a href=&quot;#第一步运行安装程序&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;运行团队或课程提供的 NVM for Windows 安装程序。安装过程中建议使用默认目录；修改目录时，应避免路径包含特殊字符，并确保符号链接目录不存在同名实体文件夹。&lt;/p&gt;
&lt;p&gt;如果安装程序询问是否接管已有 Node.js，推荐先退出安装，按照前文卸载独立版 Node.js 后再重新安装，避免路径冲突。&lt;/p&gt;
&lt;h3&gt;第二步：重新打开终端&lt;a href=&quot;#第二步重新打开终端&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;安装完成后，关闭并重新打开命令提示符或 PowerShell。切换 Node.js 版本时，Windows 通常需要管理员权限，因此建议以管理员身份打开终端。&lt;/p&gt;
&lt;p&gt;执行以下命令验证 NVM for Windows：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;部分旧版本也支持：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; -v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731085605223.png&quot; alt=&quot;NVM for Windows 版本检查&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;NVM for Windows 版本检查&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;安装和切换 Node.js 版本&lt;a href=&quot;#安装和切换-nodejs-版本&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;安装当前项目版本&lt;a href=&quot;#安装当前项目版本&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;执行以下命令安装本项目要求的 Node.js：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; 22.17.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安装完成后切换到该版本：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; use&lt;/span&gt;&lt;span&gt; 22.17.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;切换时若 Windows 弹出权限确认窗口，应在确认命令来源无误后允许操作。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731085607937.png&quot; alt=&quot;切换到 Node.js 22.17.0&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;切换到 Node.js 22.17.0&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;验证当前版本&lt;a href=&quot;#验证当前版本&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;执行以下命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; current&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;node&lt;/span&gt;&lt;span&gt; -v&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; -v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也可以查看本机已安装的全部 Node.js 版本：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;旧版本的 NVM for Windows 也可使用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; ls&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;列表中带星号的版本是当前生效版本。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731085609706.png&quot; alt=&quot;查看已安装版本和当前版本&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;查看已安装版本和当前版本&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;旧项目版本切换示例&lt;a href=&quot;#旧项目版本切换示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;仅当旧项目明确要求 Node.js &lt;code&gt;14.20.0&lt;/code&gt; 时，再安装该版本：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;span&gt; 14.20.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731085612493.png&quot; alt=&quot;安装 Node.js 14.20.0&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;安装 Node.js 14.20.0&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;安装后可切换并查看版本：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; use&lt;/span&gt;&lt;span&gt; 14.20.0&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260731085614381.png&quot; alt=&quot;查看旧项目版本&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;查看旧项目版本&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;旧项目处理完成后，应切回当前项目版本：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; use&lt;/span&gt;&lt;span&gt; 22.17.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;启动前端项目&lt;a href=&quot;#启动前端项目&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;第一步：进入项目目录&lt;a href=&quot;#第一步进入项目目录&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;打开命令提示符或 IDE 终端，进入项目的 &lt;code&gt;webui&lt;/code&gt; 目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;项目目&lt;/span&gt;&lt;span&gt;录&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;\w&lt;/span&gt;&lt;span&gt;ebui&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;第二步：确认 Node.js 版本&lt;a href=&quot;#第二步确认-nodejs-版本&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;node&lt;/span&gt;&lt;span&gt; -v&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; -v&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当前项目应使用 Node.js &lt;code&gt;22.17.0&lt;/code&gt;。如果版本不正确，执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; use&lt;/span&gt;&lt;span&gt; 22.17.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;第三步：安装项目依赖&lt;a href=&quot;#第三步安装项目依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;首次运行项目或依赖发生变化时，需要先安装依赖。&lt;/p&gt;
&lt;p&gt;项目已提交且未修改 &lt;code&gt;package-lock.json&lt;/code&gt; 时，可优先使用可重复安装命令：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; ci&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;没有 &lt;code&gt;package-lock.json&lt;/code&gt;，或需要更新锁文件时，使用：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; install&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不要在同一项目中随意混用 npm、Yarn 和 pnpm，否则可能同时生成多个锁文件并造成依赖版本不一致。&lt;/p&gt;
&lt;h3&gt;第四步：启动开发服务器&lt;a href=&quot;#第四步启动开发服务器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;npm&lt;/span&gt;&lt;span&gt; run&lt;/span&gt;&lt;span&gt; dev&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动成功后，应以终端输出的地址为准。Vite 项目的默认地址通常为：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;http://localhost:5173&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果 &lt;code&gt;5173&lt;/code&gt; 端口已被占用，开发服务器可能自动选择其他端口，因此不要只根据固定地址判断是否启动成功。&lt;/p&gt;
&lt;h2&gt;常见问题排查&lt;a href=&quot;#常见问题排查&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;nvm use&lt;/code&gt; 执行成功，但 Node.js 版本没有变化&lt;a href=&quot;#nvm-use-执行成功但-nodejs-版本没有变化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;依次检查以下项目：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;以管理员身份重新打开终端。&lt;/li&gt;
&lt;li&gt;关闭旧终端窗口后再重新验证。&lt;/li&gt;
&lt;li&gt;执行 &lt;code&gt;where node&lt;/code&gt;，检查是否存在独立版 Node.js 的路径冲突。&lt;/li&gt;
&lt;li&gt;执行 &lt;code&gt;nvm debug&lt;/code&gt;，查看 NVM for Windows 检测到的问题。&lt;/li&gt;
&lt;li&gt;确认 NVM 的符号链接目录没有被同名实体目录占用。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;提示找不到 &lt;code&gt;node&lt;/code&gt; 或 &lt;code&gt;npm&lt;/code&gt;&lt;a href=&quot;#提示找不到-node-或-npm&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;先执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;nvm&lt;/span&gt;&lt;span&gt; use&lt;/span&gt;&lt;span&gt; 22.17.0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后关闭并重新打开终端。如果仍然失败，应检查 &lt;code&gt;NVM_HOME&lt;/code&gt;、&lt;code&gt;NVM_SYMLINK&lt;/code&gt; 和 &lt;code&gt;PATH&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;npm install&lt;/code&gt; 或 &lt;code&gt;npm ci&lt;/code&gt; 失败&lt;a href=&quot;#npm-install-或-npm-ci-失败&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;重点检查：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;当前 Node.js 版本是否满足项目要求。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;package.json&lt;/code&gt; 与 &lt;code&gt;package-lock.json&lt;/code&gt; 是否一致。&lt;/li&gt;
&lt;li&gt;是否在正确的 &lt;code&gt;webui&lt;/code&gt; 目录中执行命令。&lt;/li&gt;
&lt;li&gt;网络、代理、镜像和私有仓库认证配置是否有效。&lt;/li&gt;
&lt;li&gt;是否混用了不同包管理器生成的锁文件。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;code&gt;npm run dev&lt;/code&gt; 提示脚本不存在&lt;a href=&quot;#npm-run-dev-提示脚本不存在&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;打开 &lt;code&gt;package.json&lt;/code&gt;，确认 &lt;code&gt;scripts&lt;/code&gt; 中是否定义了 &lt;code&gt;dev&lt;/code&gt;。&lt;code&gt;npm run dev&lt;/code&gt; 只是执行项目声明的脚本，并不是所有前端项目都固定使用这一命令。&lt;/p&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:web</category></item><item><title>Java 异常处理</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/javase/java-yi-chang-chu-li</link><guid isPermaLink="false">learn/hyxy/javase/java-yi-chang-chu-li</guid><description>Java 异常处理
异常处理用于描述、传递和处理程序执行期间出现的异常情况。合理使用异常可以帮助定位错误，并在可恢复的场景下采取补救措施。
异常机制不能替代正常的业务判断，也不能保证程序在任何情况下都继续运行。
一、异常体系
image-001
Java 中所有可以被抛出的对象都继承自</description><pubDate>Thu, 30 Jul 2026 12:22:00 GMT</pubDate><content:encoded>&lt;h1&gt;Java 异常处理&lt;a href=&quot;#java-异常处理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;异常处理用于描述、传递和处理程序执行期间出现的异常情况。合理使用异常可以帮助定位错误，并在可恢复的场景下采取补救措施。&lt;/p&gt;
&lt;p&gt;异常机制不能替代正常的业务判断，也不能保证程序在任何情况下都继续运行。&lt;/p&gt;
&lt;h2&gt;一、异常体系&lt;a href=&quot;#一异常体系&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730202139949.png&quot; alt=&quot;image-001&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-001&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Java 中所有可以被抛出的对象都继承自 &lt;code&gt;Throwable&lt;/code&gt;。它主要分为 &lt;code&gt;Error&lt;/code&gt; 和 &lt;code&gt;Exception&lt;/code&gt; 两大类。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;Error&lt;/code&gt;&lt;a href=&quot;#error&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Error&lt;/code&gt; 通常表示 JVM 或运行环境中的严重问题，例如 &lt;code&gt;OutOfMemoryError&lt;/code&gt;。这类问题往往不是普通业务代码能够恢复的，因此一般不在业务代码中捕获后继续执行。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;Exception&lt;/code&gt;&lt;a href=&quot;#exception&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Exception&lt;/code&gt; 表示程序可能处理的异常情况，可以继续分为运行时异常和受检查异常。&lt;/p&gt;
&lt;h4&gt;运行时异常&lt;a href=&quot;#运行时异常&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;RuntimeException&lt;/code&gt; 及其子类属于运行时异常。编译器不强制要求捕获或声明，常见类型包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;NullPointerException&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ArrayIndexOutOfBoundsException&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ClassCastException&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ArithmeticException&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IllegalArgumentException&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;运行时异常通常与参数不合法、对象状态错误或程序逻辑缺陷有关，应优先通过校验和修正代码来避免，而不是依赖大量 &lt;code&gt;catch&lt;/code&gt; 隐藏问题。&lt;/p&gt;
&lt;h4&gt;受检查异常&lt;a href=&quot;#受检查异常&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;除 &lt;code&gt;RuntimeException&lt;/code&gt; 及其子类之外的 &lt;code&gt;Exception&lt;/code&gt; 通常属于受检查异常，例如 &lt;code&gt;IOException&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;编译器要求程序采用以下方式之一：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用 &lt;code&gt;try-catch&lt;/code&gt; 捕获。&lt;/li&gt;
&lt;li&gt;使用 &lt;code&gt;throws&lt;/code&gt; 声明并继续向调用者传播。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;“受检查”发生在编译阶段，但异常对象是在程序运行到相关语句时才可能产生。&lt;/p&gt;
&lt;h2&gt;二、使用 &lt;code&gt;try-catch-finally&lt;/code&gt;&lt;a href=&quot;#二使用-try-catch-finally&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;基本语法&lt;a href=&quot;#基本语法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 可能出现异常的代码&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (SpecificException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 处理特定异常&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (Exception &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 处理其他异常&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;finally&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 通常用于释放资源或执行收尾操作&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;执行规则如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;try&lt;/code&gt; 中没有抛出异常时，不会执行对应的 &lt;code&gt;catch&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;try&lt;/code&gt; 中抛出异常时，JVM 会从上到下寻找第一个类型匹配的 &lt;code&gt;catch&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;较具体的子类异常必须写在较宽泛的父类异常之前，否则后面的分支无法到达。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;finally&lt;/code&gt; 通常都会执行，但 JVM 被强制终止、进程崩溃或执行 &lt;code&gt;System.exit()&lt;/code&gt; 等特殊情况除外。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;示例&lt;a href=&quot;#示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.InputMismatchException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.Scanner;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; ExceptionDemo&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Scanner scanner &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Scanner&lt;/span&gt;&lt;span&gt;(System.in);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; scanner.&lt;/span&gt;&lt;span&gt;nextInt&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            int&lt;/span&gt;&lt;span&gt; j &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; scanner.&lt;/span&gt;&lt;span&gt;nextInt&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            int&lt;/span&gt;&lt;span&gt; result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;/&lt;/span&gt;&lt;span&gt; j;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;相除结果：&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; result);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            int&lt;/span&gt;&lt;span&gt;[] arr &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt;[&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(arr[i]);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;计算完毕&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (ArithmeticException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;除数不能为零&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (ArrayIndexOutOfBoundsException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;数组索引越界&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (InputMismatchException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;请输入整数&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (Exception &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;程序出现其他异常&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            e.&lt;/span&gt;&lt;span&gt;printStackTrace&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;finally&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            scanner.&lt;/span&gt;&lt;span&gt;close&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;输入资源已关闭&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;程序继续执行&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;在实际项目中，不应只输出模糊提示后忽略异常。通常需要记录异常栈、返回明确错误信息，或将异常转换为当前业务层能够理解的类型。&lt;/p&gt;
&lt;h2&gt;三、使用 &lt;code&gt;try-with-resources&lt;/code&gt;&lt;a href=&quot;#三使用-try-with-resources&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;try-with-resources&lt;/code&gt; 从 Java 7 开始提供，用于自动关闭资源。资源对象必须实现 &lt;code&gt;AutoCloseable&lt;/code&gt; 接口。&lt;/p&gt;
&lt;h3&gt;传统写法&lt;a href=&quot;#传统写法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.io.FileInputStream;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.io.IOException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; ResourceDemo&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        FileInputStream input &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            input &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; FileInputStream&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;d:/a.txt&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(input.&lt;/span&gt;&lt;span&gt;read&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (IOException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            e.&lt;/span&gt;&lt;span&gt;printStackTrace&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;finally&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            if&lt;/span&gt;&lt;span&gt; (input &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    input.&lt;/span&gt;&lt;span&gt;close&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (IOException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    e.&lt;/span&gt;&lt;span&gt;printStackTrace&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;关闭前必须进行空值判断，否则创建资源失败时，&lt;code&gt;finally&lt;/code&gt; 中可能再次出现 &lt;code&gt;NullPointerException&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;推荐写法&lt;a href=&quot;#推荐写法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.io.FileInputStream;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.io.FileOutputStream;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.io.IOException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; CopyFileDemo&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                FileInputStream input &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; FileInputStream&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;d:/a.txt&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                FileOutputStream output &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; FileOutputStream&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;d:/b.txt&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        ) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            input.&lt;/span&gt;&lt;span&gt;transferTo&lt;/span&gt;&lt;span&gt;(output);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (IOException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            e.&lt;/span&gt;&lt;span&gt;printStackTrace&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;程序继续执行&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;注意事项：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;try&lt;/code&gt; 圆括号中的资源必须实现 &lt;code&gt;AutoCloseable&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;声明多个资源时，关闭顺序与声明顺序相反。&lt;/li&gt;
&lt;li&gt;资源变量不能在 &lt;code&gt;try&lt;/code&gt; 块中重新赋值。&lt;/li&gt;
&lt;li&gt;从 Java 9 开始，也可以使用在外部声明且满足“实际不可变”条件的资源变量。&lt;/li&gt;
&lt;li&gt;如果业务代码和 &lt;code&gt;close()&lt;/code&gt; 同时抛出异常，关闭资源时产生的异常会作为受抑制异常保存，可通过 &lt;code&gt;getSuppressed()&lt;/code&gt; 获取。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;四、使用 &lt;code&gt;throws&lt;/code&gt; 声明异常&lt;a href=&quot;#四使用-throws-声明异常&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;throws&lt;/code&gt; 写在方法或构造器声明之后，表示当前方法不在这里捕获该异常，而是允许异常继续向调用者传播。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.io.FileInputStream;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.io.FileNotFoundException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; FileService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; FileInputStream &lt;/span&gt;&lt;span&gt;openFile&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;path&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; FileNotFoundException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; FileInputStream&lt;/span&gt;&lt;span&gt;(path);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;throws&lt;/code&gt; 本身并没有处理异常。调用者仍然需要捕获该异常，或者继续使用 &lt;code&gt;throws&lt;/code&gt; 向上声明。&lt;/p&gt;
&lt;p&gt;方法可以声明多个异常：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; execute&lt;/span&gt;&lt;span&gt;() throws FirstException, SecondException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 方法体&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;若声明了父类异常，通常不必再重复声明它的子类异常。&lt;/p&gt;
&lt;h2&gt;五、使用 &lt;code&gt;throw&lt;/code&gt; 抛出异常&lt;a href=&quot;#五使用-throw-抛出异常&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;throw&lt;/code&gt; 用于在方法体中抛出一个具体的异常对象。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; copy&lt;/span&gt;&lt;span&gt;(String sourcePath, String targetPath) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    if&lt;/span&gt;&lt;span&gt; (sourcePath &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; ||&lt;/span&gt;&lt;span&gt; targetPath &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        throw&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; IllegalArgumentException&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;源路径和目标路径不能为空&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 执行复制操作&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;程序执行到 &lt;code&gt;throw&lt;/code&gt; 后，当前代码路径会立即中断，控制权交给能够处理该异常的调用层。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;throw&lt;/code&gt; 与 &lt;code&gt;throws&lt;/code&gt; 的区别&lt;a href=&quot;#throw-与-throws-的区别&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;关键字&lt;/th&gt;&lt;th&gt;使用位置&lt;/th&gt;&lt;th&gt;作用&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;throw&lt;/code&gt;&lt;/td&gt;&lt;td&gt;方法体内部&lt;/td&gt;&lt;td&gt;抛出一个具体异常对象&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;throws&lt;/code&gt;&lt;/td&gt;&lt;td&gt;方法或构造器声明后&lt;/td&gt;&lt;td&gt;声明可能向调用者传播的异常类型&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;六、自定义异常&lt;a href=&quot;#六自定义异常&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;当 JDK 提供的异常类型无法清楚表达业务含义时，可以定义业务异常。&lt;/p&gt;
&lt;h3&gt;自定义受检查异常&lt;a href=&quot;#自定义受检查异常&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; InvalidEmailAddressException&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; Exception&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; InvalidEmailAddressException&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        super&lt;/span&gt;&lt;span&gt;(message);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; EmailManager&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; sendEmail&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            String &lt;/span&gt;&lt;span&gt;recipient&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            String &lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            String &lt;/span&gt;&lt;span&gt;content&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; InvalidEmailAddressException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (recipient &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; ||&lt;/span&gt;&lt;span&gt; recipient.&lt;/span&gt;&lt;span&gt;isBlank&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            throw&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; InvalidEmailAddressException&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;收件人地址不能为空&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;发送邮件成功&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;继承 &lt;code&gt;Exception&lt;/code&gt; 后，调用者必须捕获或声明该异常。&lt;/p&gt;
&lt;h3&gt;自定义运行时异常&lt;a href=&quot;#自定义运行时异常&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;若异常表示参数错误、业务规则不满足，且不希望强制每一层代码显式捕获，也可以继承 &lt;code&gt;RuntimeException&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; InvalidEmailAddressException&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; RuntimeException&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; InvalidEmailAddressException&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        super&lt;/span&gt;&lt;span&gt;(message);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;选择受检查异常还是运行时异常，应结合调用者是否能够恢复、项目异常处理规范以及框架约定决定。&lt;/p&gt;
&lt;h2&gt;七、异常处理建议&lt;a href=&quot;#七异常处理建议&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;捕获能够真正处理的异常，不要无意义地捕获后忽略。&lt;/li&gt;
&lt;li&gt;优先捕获具体异常，避免直接使用过于宽泛的 &lt;code&gt;Exception&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;保留原始异常作为 &lt;code&gt;cause&lt;/code&gt;，不要丢失问题根因。&lt;/li&gt;
&lt;li&gt;不要把异常用于普通流程控制。&lt;/li&gt;
&lt;li&gt;资源优先使用 &lt;code&gt;try-with-resources&lt;/code&gt; 管理。&lt;/li&gt;
&lt;li&gt;对外返回稳定的错误信息，对内记录完整异常栈和必要上下文。&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:javaSE</category></item><item><title>Java 日期与时间类</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/javase/java-ri-qi-yu-shi-jian-lei</link><guid isPermaLink="false">learn/hyxy/javase/java-ri-qi-yu-shi-jian-lei</guid><description>Java 日期与时间类
Java 中常见的日期时间 API 可以分为两类：

旧版 API：Date、Calendar、SimpleDateFormat。
Java 8 新 API：LocalDate、LocalDateTime、Instant、DateTimeFormatter 等。

旧版</description><pubDate>Thu, 30 Jul 2026 12:20:36 GMT</pubDate><content:encoded>&lt;h1&gt;Java 日期与时间类&lt;a href=&quot;#java-日期与时间类&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Java 中常见的日期时间 API 可以分为两类：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;旧版 API：&lt;code&gt;Date&lt;/code&gt;、&lt;code&gt;Calendar&lt;/code&gt;、&lt;code&gt;SimpleDateFormat&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;Java 8 新 API：&lt;code&gt;LocalDate&lt;/code&gt;、&lt;code&gt;LocalDateTime&lt;/code&gt;、&lt;code&gt;Instant&lt;/code&gt;、&lt;code&gt;DateTimeFormatter&lt;/code&gt; 等。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;旧版 API 在维护历史代码时仍会遇到，但新项目通常优先使用 &lt;code&gt;java.time&lt;/code&gt; 包。&lt;/p&gt;
&lt;h2&gt;一、时间戳与时区&lt;a href=&quot;#一时间戳与时区&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Unix 时间戳通常表示从 &lt;code&gt;1970-01-01T00:00:00Z&lt;/code&gt; 开始经过的时间。&lt;code&gt;Date&lt;/code&gt; 使用毫秒精度保存时间点。&lt;/p&gt;
&lt;p&gt;北京时间通常采用 &lt;code&gt;UTC+8&lt;/code&gt;。时区会影响时间点如何显示为年月日和时分秒，但不会改变时间点本身。&lt;/p&gt;
&lt;h2&gt;二、&lt;code&gt;Date&lt;/code&gt; 类&lt;a href=&quot;#二date-类&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;java.util.Date&lt;/code&gt; 表示时间轴上的一个时间点，内部核心值是从 Unix 纪元开始计算的毫秒数。它并不是简单地分别保存年、月、日、时、分、秒。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Date&lt;/code&gt; 中许多直接操作年月日的方法已经过时，日期计算应使用 &lt;code&gt;Calendar&lt;/code&gt; 或更推荐的 &lt;code&gt;java.time&lt;/code&gt; API。&lt;/p&gt;
&lt;h3&gt;构造器&lt;a href=&quot;#构造器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Date now &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Date&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;无参构造器创建表示当前时间的对象。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Date date &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Date&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1_000_000L&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;传入的 &lt;code&gt;long&lt;/code&gt; 值表示从 Unix 纪元开始经过的毫秒数。&lt;/p&gt;
&lt;h3&gt;常用方法&lt;a href=&quot;#常用方法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Date date &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Date&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; timestamp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; date.&lt;/span&gt;&lt;span&gt;getTime&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;date.&lt;/span&gt;&lt;span&gt;setTime&lt;/span&gt;&lt;span&gt;(timestamp &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; 1_000L&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;getTime()&lt;/code&gt;：获取毫秒时间戳。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;setTime(long time)&lt;/code&gt;：修改该对象表示的时间点。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;Date&lt;/code&gt; 是可变对象，调用 &lt;code&gt;setTime()&lt;/code&gt; 会改变原对象。&lt;/p&gt;
&lt;h2&gt;三、&lt;code&gt;Calendar&lt;/code&gt; 类&lt;a href=&quot;#三calendar-类&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Calendar&lt;/code&gt; 是旧版日历计算类，可以根据时区和区域设置处理年月日等字段。&lt;/p&gt;
&lt;p&gt;它的构造器通常不直接调用，而是通过 &lt;code&gt;getInstance()&lt;/code&gt; 获取实例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Calendar calendar &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Calendar.&lt;/span&gt;&lt;span&gt;getInstance&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;获取和修改日期字段&lt;a href=&quot;#获取和修改日期字段&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Calendar calendar &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Calendar.&lt;/span&gt;&lt;span&gt;getInstance&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;calendar.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(Calendar.DATE, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; year &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; calendar.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(Calendar.YEAR);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; month &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; calendar.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(Calendar.MONTH) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; day &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; calendar.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(Calendar.DAY_OF_MONTH);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(year &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;-&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; month &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;-&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; day);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Calendar.MONTH&lt;/code&gt; 从 &lt;code&gt;0&lt;/code&gt; 开始，因此显示月份时通常需要加 &lt;code&gt;1&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;add()&lt;/code&gt; 的参数可以为正数或负数，用于增加或减少时间。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Calendar&lt;/code&gt; 也是可变对象。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;与 &lt;code&gt;Date&lt;/code&gt; 相互转换&lt;a href=&quot;#与-date-相互转换&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Calendar calendar &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Calendar.&lt;/span&gt;&lt;span&gt;getInstance&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Date dateFromCalendar &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; calendar.&lt;/span&gt;&lt;span&gt;getTime&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Date date &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Date&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;100_000_000L&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Calendar anotherCalendar &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Calendar.&lt;/span&gt;&lt;span&gt;getInstance&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;anotherCalendar.&lt;/span&gt;&lt;span&gt;setTime&lt;/span&gt;&lt;span&gt;(date);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;calendar.getTime()&lt;/code&gt;：将 &lt;code&gt;Calendar&lt;/code&gt; 当前表示的时间转换为 &lt;code&gt;Date&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;calendar.setTime(date)&lt;/code&gt;：让 &lt;code&gt;Calendar&lt;/code&gt; 使用指定 &lt;code&gt;Date&lt;/code&gt; 的时间点。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;四、&lt;code&gt;SimpleDateFormat&lt;/code&gt; 类&lt;a href=&quot;#四simpledateformat-类&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;SimpleDateFormat&lt;/code&gt; 用于在 &lt;code&gt;Date&lt;/code&gt; 与字符串之间进行格式化和解析。&lt;/p&gt;
&lt;p&gt;常见格式符号如下：&lt;/p&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;符号&lt;/th&gt;&lt;th&gt;含义&lt;/th&gt;&lt;th&gt;示例&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;yyyy&lt;/code&gt;&lt;/td&gt;&lt;td&gt;四位年份&lt;/td&gt;&lt;td&gt;&lt;code&gt;2026&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;MM&lt;/code&gt;&lt;/td&gt;&lt;td&gt;两位月份&lt;/td&gt;&lt;td&gt;&lt;code&gt;01&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;dd&lt;/code&gt;&lt;/td&gt;&lt;td&gt;两位日期&lt;/td&gt;&lt;td&gt;&lt;code&gt;25&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;HH&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;24&lt;/code&gt; 小时制小时&lt;/td&gt;&lt;td&gt;&lt;code&gt;16&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;mm&lt;/code&gt;&lt;/td&gt;&lt;td&gt;分钟&lt;/td&gt;&lt;td&gt;&lt;code&gt;30&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ss&lt;/code&gt;&lt;/td&gt;&lt;td&gt;秒&lt;/td&gt;&lt;td&gt;&lt;code&gt;45&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;格式符号区分大小写。例如，&lt;code&gt;MM&lt;/code&gt; 表示月份，&lt;code&gt;mm&lt;/code&gt; 表示分钟。&lt;/p&gt;
&lt;h3&gt;将 &lt;code&gt;Date&lt;/code&gt; 格式化为字符串&lt;a href=&quot;#将-date-格式化为字符串&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.text.SimpleDateFormat;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.Date;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; FormatDateDemo&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SimpleDateFormat formatter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; SimpleDateFormat&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;yyyy-MM-dd HH:mm:ss&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Date now &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Date&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String text &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; formatter.&lt;/span&gt;&lt;span&gt;format&lt;/span&gt;&lt;span&gt;(now);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(text);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;将字符串解析为 &lt;code&gt;Date&lt;/code&gt;&lt;a href=&quot;#将字符串解析为-date&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.text.ParseException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.text.SimpleDateFormat;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.Date;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; ParseDateDemo&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SimpleDateFormat formatter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; SimpleDateFormat&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;yyyy-MM-dd&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        formatter.&lt;/span&gt;&lt;span&gt;setLenient&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String text &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;2026-01-25&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Date date &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; formatter.&lt;/span&gt;&lt;span&gt;parse&lt;/span&gt;&lt;span&gt;(text);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(date);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (ParseException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;日期格式不正确&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;setLenient(false)&lt;/code&gt; 用于关闭宽松解析。例如，在严格模式下，&lt;code&gt;2026-02-30&lt;/code&gt; 会解析失败，而不是自动调整到下一个月。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SimpleDateFormat&lt;/code&gt; 不是线程安全的，不应把同一个实例作为共享对象供多个线程同时使用。&lt;/p&gt;
&lt;h2&gt;五、旧版 API 应用&lt;a href=&quot;#五旧版-api-应用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;指定日期增加十五天&lt;a href=&quot;#指定日期增加十五天&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;将 &lt;code&gt;20260122&lt;/code&gt; 增加十五天，并按中文日期格式输出：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.text.ParseException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.text.SimpleDateFormat;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.Calendar;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.Date;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; AddDaysLegacyDemo&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String text &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;20260122&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SimpleDateFormat formatter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; SimpleDateFormat&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;yyyyMMdd&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        formatter.&lt;/span&gt;&lt;span&gt;setLenient&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Date date &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; formatter.&lt;/span&gt;&lt;span&gt;parse&lt;/span&gt;&lt;span&gt;(text);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Calendar calendar &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Calendar.&lt;/span&gt;&lt;span&gt;getInstance&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            calendar.&lt;/span&gt;&lt;span&gt;setTime&lt;/span&gt;&lt;span&gt;(date);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            calendar.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(Calendar.DATE, &lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            formatter.&lt;/span&gt;&lt;span&gt;applyPattern&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;yyyy年MM月dd日&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(formatter.&lt;/span&gt;&lt;span&gt;format&lt;/span&gt;&lt;span&gt;(calendar.&lt;/span&gt;&lt;span&gt;getTime&lt;/span&gt;&lt;span&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (ParseException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;日期格式不正确&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;计算两个时间点的毫秒差&lt;a href=&quot;#计算两个时间点的毫秒差&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; differenceMillis &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; endDate.&lt;/span&gt;&lt;span&gt;getTime&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; startDate.&lt;/span&gt;&lt;span&gt;getTime&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;直接除以一天的毫秒数只能得到固定时长意义上的天数。如果时间范围跨越夏令时变化，结果可能与日历日期差不同。因此，计算日期之间相差多少天时，更适合使用 &lt;code&gt;LocalDate&lt;/code&gt; 和 &lt;code&gt;ChronoUnit.DAYS&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;六、Java 8 日期时间 API&lt;a href=&quot;#六java-8-日期时间-api&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;java.time&lt;/code&gt; API 的类型设计更清晰，并且大多数核心类不可变、线程安全。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;LocalDate&lt;/code&gt;&lt;a href=&quot;#localdate&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;LocalDate&lt;/code&gt; 表示不带时区的日期，例如生日或课程日期。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.time.LocalDate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.time.format.DateTimeFormatter;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; LocalDateDemo&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        DateTimeFormatter inputFormatter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; DateTimeFormatter.&lt;/span&gt;&lt;span&gt;ofPattern&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;yyyyMMdd&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        DateTimeFormatter outputFormatter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; DateTimeFormatter.&lt;/span&gt;&lt;span&gt;ofPattern&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;yyyy年MM月dd日&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        LocalDate date &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; LocalDate.&lt;/span&gt;&lt;span&gt;parse&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;20260122&quot;&lt;/span&gt;&lt;span&gt;, inputFormatter);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        LocalDate result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; date.&lt;/span&gt;&lt;span&gt;plusDays&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;15&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(result.&lt;/span&gt;&lt;span&gt;format&lt;/span&gt;&lt;span&gt;(outputFormatter));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;计算日期差&lt;a href=&quot;#计算日期差&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.time.LocalDate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.time.format.DateTimeFormatter;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.time.temporal.ChronoUnit;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; DateDifferenceDemo&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        DateTimeFormatter formatter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; DateTimeFormatter.&lt;/span&gt;&lt;span&gt;ofPattern&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;yyyyMMdd&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        LocalDate startDate &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; LocalDate.&lt;/span&gt;&lt;span&gt;parse&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;20260122&quot;&lt;/span&gt;&lt;span&gt;, formatter);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        LocalDate endDate &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; LocalDate.&lt;/span&gt;&lt;span&gt;parse&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;20260302&quot;&lt;/span&gt;&lt;span&gt;, formatter);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        long&lt;/span&gt;&lt;span&gt; days &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ChronoUnit.DAYS.&lt;/span&gt;&lt;span&gt;between&lt;/span&gt;&lt;span&gt;(startDate, endDate);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(days);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;常用类型&lt;a href=&quot;#常用类型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;









































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;类型&lt;/th&gt;&lt;th&gt;适用场景&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;LocalDate&lt;/code&gt;&lt;/td&gt;&lt;td&gt;只需要年月日，不需要时区&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;LocalTime&lt;/code&gt;&lt;/td&gt;&lt;td&gt;只需要时分秒&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;LocalDateTime&lt;/code&gt;&lt;/td&gt;&lt;td&gt;需要日期和时间，但不包含时区&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Instant&lt;/code&gt;&lt;/td&gt;&lt;td&gt;时间轴上的时间点，适合记录时间戳&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ZonedDateTime&lt;/code&gt;&lt;/td&gt;&lt;td&gt;需要明确时区规则的日期时间&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Duration&lt;/code&gt;&lt;/td&gt;&lt;td&gt;表示基于秒和纳秒的时长&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Period&lt;/code&gt;&lt;/td&gt;&lt;td&gt;表示基于年、月、日的日期差&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DateTimeFormatter&lt;/code&gt;&lt;/td&gt;&lt;td&gt;日期时间的格式化和解析&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;新代码应根据业务含义选择类型，而不是所有时间都使用 &lt;code&gt;Date&lt;/code&gt; 或字符串保存。&lt;/p&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:javaSE</category></item><item><title>TCP 三次握手和四次挥手</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/web/tcp-san-ci-wo-shou-he-si-ci-hui-shou</link><guid isPermaLink="false">learn/hyxy/web/tcp-san-ci-wo-shou-he-si-ci-hui-shou</guid><description>TCP 三次握手和四次挥手
TCP 是面向连接的传输层协议。通信双方在传输应用数据前，需要通过三次握手建立连接；数据传输结束后，通常通过四个报文段释放双向连接。
TCP 首部中的相关字段
image-001
序列号 seq
序列号字段占 32 位。TCP</description><pubDate>Thu, 30 Jul 2026 12:19:23 GMT</pubDate><content:encoded>&lt;h1&gt;TCP 三次握手和四次挥手&lt;a href=&quot;#tcp-三次握手和四次挥手&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;TCP 是面向连接的传输层协议。通信双方在传输应用数据前，需要通过三次握手建立连接；数据传输结束后，通常通过四个报文段释放双向连接。&lt;/p&gt;
&lt;h2&gt;TCP 首部中的相关字段&lt;a href=&quot;#tcp-首部中的相关字段&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730201849438.png&quot; alt=&quot;image-001&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-001&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;序列号 &lt;code&gt;seq&lt;/code&gt;&lt;a href=&quot;#序列号-seq&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;序列号字段占 &lt;code&gt;32&lt;/code&gt; 位。TCP 会对字节流中的数据进行编号，报文段中的序列号通常表示该报文段所携带数据的第一个字节编号。&lt;/p&gt;
&lt;p&gt;建立连接时，通信双方会分别选择初始序列号。&lt;code&gt;SYN&lt;/code&gt; 和 &lt;code&gt;FIN&lt;/code&gt; 即使不携带应用数据，也各自会消耗一个序列号。&lt;/p&gt;
&lt;h3&gt;确认号 &lt;code&gt;ack&lt;/code&gt;&lt;a href=&quot;#确认号-ack&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;确认号字段占 &lt;code&gt;32&lt;/code&gt; 位，表示接收方期望收到的下一个字节序号。&lt;/p&gt;
&lt;p&gt;例如，若已经正确收到对方序号为 &lt;code&gt;100&lt;/code&gt; 到 &lt;code&gt;199&lt;/code&gt; 的数据，则确认号通常为 &lt;code&gt;200&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;ACK&lt;/code&gt; 标志位&lt;a href=&quot;#ack-标志位&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;ACK&lt;/code&gt; 占 &lt;code&gt;1&lt;/code&gt; 位。当 &lt;code&gt;ACK&lt;/code&gt; 为 &lt;code&gt;1&lt;/code&gt; 时，确认号字段有效。连接建立后，绝大多数 TCP 报文段都会设置该标志位。&lt;/p&gt;
&lt;p&gt;需要区分：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;小写的 &lt;code&gt;ack&lt;/code&gt; 通常表示确认号字段的值。&lt;/li&gt;
&lt;li&gt;大写的 &lt;code&gt;ACK&lt;/code&gt; 表示 TCP 首部中的确认标志位。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;code&gt;SYN&lt;/code&gt; 标志位&lt;a href=&quot;#syn-标志位&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;SYN&lt;/code&gt; 用于建立连接并同步双方的初始序列号。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SYN=1&lt;/code&gt;、&lt;code&gt;ACK=0&lt;/code&gt;：通常表示连接请求。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SYN=1&lt;/code&gt;、&lt;code&gt;ACK=1&lt;/code&gt;：通常表示同意建立连接并确认对方的请求。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;code&gt;FIN&lt;/code&gt; 标志位&lt;a href=&quot;#fin-标志位&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;FIN&lt;/code&gt; 表示发送方已经没有数据需要发送，请求关闭当前方向上的连接。TCP 是全双工协议，因此一个方向关闭后，另一个方向仍然可以继续传输数据。&lt;/p&gt;
&lt;h2&gt;三次握手&lt;a href=&quot;#三次握手&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730201852696.png&quot; alt=&quot;image-002&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-002&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;假设客户端的初始序列号为 &lt;code&gt;x&lt;/code&gt;，服务器的初始序列号为 &lt;code&gt;y&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;第一次握手：客户端发送 &lt;code&gt;SYN&lt;/code&gt;&lt;a href=&quot;#第一次握手客户端发送-syn&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;客户端向服务器发送连接请求：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;SYN=1, seq=x&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;发送后，客户端从 &lt;code&gt;CLOSED&lt;/code&gt; 进入 &lt;code&gt;SYN-SENT&lt;/code&gt; 状态。&lt;/p&gt;
&lt;h3&gt;第二次握手：服务器发送 &lt;code&gt;SYN+ACK&lt;/code&gt;&lt;a href=&quot;#第二次握手服务器发送-synack&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;服务器收到客户端的请求后，确认客户端的序列号，并发送自己的初始序列号：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;SYN=1, ACK=1, seq=y, ack=x+1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;发送后，服务器从 &lt;code&gt;LISTEN&lt;/code&gt; 进入 &lt;code&gt;SYN-RECEIVED&lt;/code&gt; 状态。&lt;/p&gt;
&lt;h3&gt;第三次握手：客户端发送 &lt;code&gt;ACK&lt;/code&gt;&lt;a href=&quot;#第三次握手客户端发送-ack&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;客户端收到服务器的响应后，再发送确认报文：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;ACK=1, seq=x+1, ack=y+1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;服务器收到该确认后，双方进入 &lt;code&gt;ESTABLISHED&lt;/code&gt; 状态，可以传输应用数据。&lt;/p&gt;
&lt;p&gt;第三次握手中的纯 &lt;code&gt;ACK&lt;/code&gt; 报文如果不携带数据，本身不会额外消耗序列号。&lt;/p&gt;
&lt;h2&gt;为什么需要三次握手&lt;a href=&quot;#为什么需要三次握手&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;三次握手主要完成以下工作：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;确认双方的发送能力和接收能力基本正常。&lt;/li&gt;
&lt;li&gt;同步双方各自的初始序列号。&lt;/li&gt;
&lt;li&gt;避免失效的旧连接请求直接导致服务器建立错误连接。&lt;/li&gt;
&lt;li&gt;协商 TCP 选项，例如最大报文段长度和窗口扩大因子。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;只进行两次交互时，服务器无法确认客户端是否已经收到服务器的初始序列号和连接确认，因此需要第三次确认。&lt;/p&gt;
&lt;h2&gt;四次挥手&lt;a href=&quot;#四次挥手&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730201856734.png&quot; alt=&quot;image-003&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-003&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;下面以客户端主动关闭连接为例。假设客户端发送 &lt;code&gt;FIN&lt;/code&gt; 时的序列号为 &lt;code&gt;u&lt;/code&gt;，服务器当前序列号为 &lt;code&gt;v&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;第一次挥手：客户端发送 &lt;code&gt;FIN&lt;/code&gt;&lt;a href=&quot;#第一次挥手客户端发送-fin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;客户端表示自己已经没有数据需要发送：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;FIN=1, ACK=1, seq=u&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;客户端进入 &lt;code&gt;FIN-WAIT-1&lt;/code&gt; 状态。&lt;code&gt;FIN&lt;/code&gt; 会消耗一个序列号。&lt;/p&gt;
&lt;h3&gt;第二次挥手：服务器确认客户端的 &lt;code&gt;FIN&lt;/code&gt;&lt;a href=&quot;#第二次挥手服务器确认客户端的-fin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;服务器收到 &lt;code&gt;FIN&lt;/code&gt; 后发送确认：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;ACK=1, seq=v, ack=u+1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;服务器进入 &lt;code&gt;CLOSE-WAIT&lt;/code&gt; 状态，客户端收到确认后进入 &lt;code&gt;FIN-WAIT-2&lt;/code&gt; 状态。&lt;/p&gt;
&lt;p&gt;此时客户端到服务器方向已经关闭，但服务器到客户端方向仍可继续传输尚未发送完的数据，这种状态称为半关闭。&lt;/p&gt;
&lt;h3&gt;第三次挥手：服务器发送 &lt;code&gt;FIN&lt;/code&gt;&lt;a href=&quot;#第三次挥手服务器发送-fin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;服务器完成剩余数据发送后，请求关闭自己的发送方向。假设此时服务器序列号为 &lt;code&gt;w&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;FIN=1, ACK=1, seq=w, ack=u+1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;服务器进入 &lt;code&gt;LAST-ACK&lt;/code&gt; 状态，等待客户端的最终确认。&lt;/p&gt;
&lt;h3&gt;第四次挥手：客户端确认服务器的 &lt;code&gt;FIN&lt;/code&gt;&lt;a href=&quot;#第四次挥手客户端确认服务器的-fin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;客户端收到服务器的 &lt;code&gt;FIN&lt;/code&gt; 后发送确认：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;ACK=1, seq=u+1, ack=w+1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;客户端进入 &lt;code&gt;TIME-WAIT&lt;/code&gt; 状态。服务器收到该确认后进入 &lt;code&gt;CLOSED&lt;/code&gt; 状态。&lt;/p&gt;
&lt;h2&gt;为什么通常需要四次挥手&lt;a href=&quot;#为什么通常需要四次挥手&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;TCP 的两个传输方向需要分别关闭。主动关闭方发送 &lt;code&gt;FIN&lt;/code&gt; 后，被动关闭方可能仍有数据需要发送，因此通常先单独确认对方的 &lt;code&gt;FIN&lt;/code&gt;，等剩余数据发送完毕后再发送自己的 &lt;code&gt;FIN&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;如果被动关闭方收到 &lt;code&gt;FIN&lt;/code&gt; 时已经没有数据需要发送，也可能把 &lt;code&gt;ACK&lt;/code&gt; 与自己的 &lt;code&gt;FIN&lt;/code&gt; 合并到同一个报文段中。此时网络上看到的报文段数量可能少于四个，但连接释放的逻辑仍然包含两个方向的关闭与确认。&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;TIME-WAIT&lt;/code&gt; 状态&lt;a href=&quot;#time-wait-状态&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;主动关闭方通常会在 &lt;code&gt;TIME-WAIT&lt;/code&gt; 状态等待 &lt;code&gt;2MSL&lt;/code&gt;。&lt;code&gt;MSL&lt;/code&gt; 表示报文段在网络中的最大生存时间。&lt;/p&gt;
&lt;p&gt;等待的主要原因有两个：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;若最后一个 &lt;code&gt;ACK&lt;/code&gt; 丢失，被动关闭方会重发 &lt;code&gt;FIN&lt;/code&gt;，主动关闭方仍能再次确认。&lt;/li&gt;
&lt;li&gt;让当前连接产生的延迟报文在网络中消失，避免影响之后使用相同四元组建立的新连接。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;TIME-WAIT&lt;/code&gt; 是 TCP 保证可靠关闭的重要机制，并不等同于程序异常。&lt;/p&gt;
&lt;h2&gt;常见状态汇总&lt;a href=&quot;#常见状态汇总&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;

















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;状态&lt;/th&gt;&lt;th&gt;含义&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;LISTEN&lt;/code&gt;&lt;/td&gt;&lt;td&gt;服务器监听连接请求&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SYN-SENT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;客户端已发送连接请求&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SYN-RECEIVED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;服务器已收到请求并等待最终确认&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ESTABLISHED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;连接已建立&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;FIN-WAIT-1&lt;/code&gt;&lt;/td&gt;&lt;td&gt;主动关闭方已发送 &lt;code&gt;FIN&lt;/code&gt;，等待确认&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;FIN-WAIT-2&lt;/code&gt;&lt;/td&gt;&lt;td&gt;主动关闭方已收到确认，等待对方的 &lt;code&gt;FIN&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;CLOSE-WAIT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;被动关闭方已确认对方的 &lt;code&gt;FIN&lt;/code&gt;，等待应用关闭连接&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;LAST-ACK&lt;/code&gt;&lt;/td&gt;&lt;td&gt;被动关闭方已发送自己的 &lt;code&gt;FIN&lt;/code&gt;，等待最终确认&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;TIME-WAIT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;主动关闭方等待 &lt;code&gt;2MSL&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;CLOSED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;连接已关闭&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:web</category></item><item><title>MySQL 查询计划详解</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/mysql/mysql-cha-xun-ji-hua-xiang-jie</link><guid isPermaLink="false">learn/hyxy/mysql/mysql-cha-xun-ji-hua-xiang-jie</guid><description>MySQL EXPLAIN 查询计划详解
EXPLAIN 用于查看 MySQL 为一条 SQL 语句生成的执行计划。通过执行计划可以分析访问顺序、索引选择、预估扫描行数以及排序、临时表等信息。
DESC 与 EXPLAIN 的区别
查看表结构
DESC 是 DESCRIBE</description><pubDate>Thu, 30 Jul 2026 12:18:04 GMT</pubDate><content:encoded>&lt;h1&gt;MySQL &lt;code&gt;EXPLAIN&lt;/code&gt; 查询计划详解&lt;a href=&quot;#mysql-explain-查询计划详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;EXPLAIN&lt;/code&gt; 用于查看 MySQL 为一条 SQL 语句生成的执行计划。通过执行计划可以分析访问顺序、索引选择、预估扫描行数以及排序、临时表等信息。&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;DESC&lt;/code&gt; 与 &lt;code&gt;EXPLAIN&lt;/code&gt; 的区别&lt;a href=&quot;#desc-与-explain-的区别&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;查看表结构&lt;a href=&quot;#查看表结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;DESC&lt;/code&gt; 是 &lt;code&gt;DESCRIBE&lt;/code&gt; 的缩写，用于查看表或视图的字段信息。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;DESC&lt;/span&gt;&lt;span&gt; employee;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;DESCRIBE employee;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这两条语句通常会显示字段名、数据类型、是否允许为 &lt;code&gt;NULL&lt;/code&gt;、索引类型、默认值和附加信息。&lt;/p&gt;
&lt;h3&gt;查看 SQL 执行计划&lt;a href=&quot;#查看-sql-执行计划&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在查询语句前添加 &lt;code&gt;EXPLAIN&lt;/code&gt;，可以查看优化器选择的执行计划。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;EXPLAIN&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; employee&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; first_name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &apos;tom&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730201731413.png&quot; alt=&quot;image-001&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-001&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;MySQL 还支持其他输出格式。例如，树形格式更便于观察执行顺序：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;EXPLAIN FORMAT&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;TREE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; employee&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; first_name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &apos;tom&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt; 会实际执行 SQL，并返回估算值与实际执行数据。对于更新或删除语句应谨慎使用，避免意外修改数据。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;EXPLAIN ANALYZE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; employee&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; first_name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &apos;tom&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;&lt;code&gt;EXPLAIN&lt;/code&gt; 常见列&lt;a href=&quot;#explain-常见列&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730201722165.png&quot; alt=&quot;image-002&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-002&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;传统表格格式通常包含以下列：&lt;/p&gt;

























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;列名&lt;/th&gt;&lt;th&gt;作用&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;id&lt;/code&gt;&lt;/td&gt;&lt;td&gt;查询块编号，可辅助判断查询块之间的执行关系&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;select_type&lt;/code&gt;&lt;/td&gt;&lt;td&gt;查询块的类型，例如简单查询、主查询、子查询或派生表&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;table&lt;/code&gt;&lt;/td&gt;&lt;td&gt;当前访问的表、别名或内部临时结果&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;partitions&lt;/code&gt;&lt;/td&gt;&lt;td&gt;预计访问的分区；未使用分区表时通常为 &lt;code&gt;NULL&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;&lt;td&gt;表访问方式，是判断索引使用情况的重要指标&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;possible_keys&lt;/code&gt;&lt;/td&gt;&lt;td&gt;优化器认为可能使用的索引&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;key&lt;/code&gt;&lt;/td&gt;&lt;td&gt;实际选择的索引&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;key_len&lt;/code&gt;&lt;/td&gt;&lt;td&gt;预计使用的索引键长度，单位为字节&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ref&lt;/code&gt;&lt;/td&gt;&lt;td&gt;与索引列比较的常量或列&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;rows&lt;/code&gt;&lt;/td&gt;&lt;td&gt;优化器估算需要检查的行数&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;filtered&lt;/code&gt;&lt;/td&gt;&lt;td&gt;经过当前表条件过滤后预计保留的百分比&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Extra&lt;/code&gt;&lt;/td&gt;&lt;td&gt;排序、临时表、覆盖索引等补充信息&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;&lt;code&gt;id&lt;/code&gt;：查询块编号&lt;a href=&quot;#id查询块编号&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;id&lt;/code&gt; 用于标识不同的查询块，但不能简单地把它当作绝对执行顺序。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;id&lt;/code&gt; 相同的多行通常属于同一个查询块，表的显示顺序反映该连接计划中的访问顺序。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;id&lt;/code&gt; 不同通常表示存在子查询、派生表或 &lt;code&gt;UNION&lt;/code&gt; 等多个查询块。&lt;/li&gt;
&lt;li&gt;某些结果行的 &lt;code&gt;id&lt;/code&gt; 可能为 &lt;code&gt;NULL&lt;/code&gt;，例如 &lt;code&gt;UNION RESULT&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;复杂 SQL 的真实执行过程还应结合 &lt;code&gt;FORMAT=TREE&lt;/code&gt; 或 &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt; 判断。&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;select_type&lt;/code&gt;：查询类型&lt;a href=&quot;#select_type查询类型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;常见取值如下：&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;取值&lt;/th&gt;&lt;th&gt;含义&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SIMPLE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;不包含 &lt;code&gt;UNION&lt;/code&gt; 或子查询的简单查询&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;PRIMARY&lt;/code&gt;&lt;/td&gt;&lt;td&gt;最外层查询&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;UNION&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;UNION&lt;/code&gt; 中第二个及后续查询块&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DEPENDENT UNION&lt;/code&gt;&lt;/td&gt;&lt;td&gt;依赖外层查询结果的 &lt;code&gt;UNION&lt;/code&gt; 查询块&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;UNION RESULT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;UNION&lt;/code&gt; 结果集&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SUBQUERY&lt;/code&gt;&lt;/td&gt;&lt;td&gt;不依赖外层查询的子查询&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DEPENDENT SUBQUERY&lt;/code&gt;&lt;/td&gt;&lt;td&gt;依赖外层查询结果的相关子查询&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DERIVED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;FROM&lt;/code&gt; 子句中的派生表&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;MATERIALIZED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;被物化后重复使用的子查询结果&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;&lt;code&gt;table&lt;/code&gt;：访问对象&lt;a href=&quot;#table访问对象&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;table&lt;/code&gt; 一般显示表名或表别名。对于优化器生成的内部结果，可能出现以下形式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;derivedN&amp;gt;&lt;/code&gt;：来自编号为 &lt;code&gt;N&lt;/code&gt; 的派生表查询块。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;unionM,N&amp;gt;&lt;/code&gt;：来自编号为 &lt;code&gt;M&lt;/code&gt;、&lt;code&gt;N&lt;/code&gt; 等查询块的 &lt;code&gt;UNION&lt;/code&gt; 结果。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;subqueryN&amp;gt;&lt;/code&gt;：被物化的子查询结果。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;code&gt;type&lt;/code&gt;：访问方式&lt;a href=&quot;#type访问方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;type&lt;/code&gt; 描述 MySQL 如何从表中读取数据。下面按通常情况下由精确到宽泛的顺序列出常见类型，但实际性能还受返回行数、数据分布和缓存等因素影响。&lt;/p&gt;

























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;类型&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;system&lt;/code&gt;&lt;/td&gt;&lt;td&gt;表被视为只有一行，是 &lt;code&gt;const&lt;/code&gt; 的特例&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;const&lt;/code&gt;&lt;/td&gt;&lt;td&gt;通过主键或唯一索引等值匹配，最多返回一行&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;eq_ref&lt;/code&gt;&lt;/td&gt;&lt;td&gt;连接时通过主键或非空唯一索引匹配，每个前表组合最多命中一行&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ref&lt;/code&gt;&lt;/td&gt;&lt;td&gt;通过普通索引或唯一索引的非完整前缀进行等值查找，可能返回多行&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;fulltext&lt;/code&gt;&lt;/td&gt;&lt;td&gt;使用全文索引&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ref_or_null&lt;/code&gt;&lt;/td&gt;&lt;td&gt;类似 &lt;code&gt;ref&lt;/code&gt;，同时额外查找 &lt;code&gt;NULL&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;index_merge&lt;/code&gt;&lt;/td&gt;&lt;td&gt;合并多个索引的扫描结果&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;unique_subquery&lt;/code&gt;&lt;/td&gt;&lt;td&gt;某些 &lt;code&gt;IN&lt;/code&gt; 子查询通过唯一索引查找&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;index_subquery&lt;/code&gt;&lt;/td&gt;&lt;td&gt;某些 &lt;code&gt;IN&lt;/code&gt; 子查询通过非唯一索引查找&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;range&lt;/code&gt;&lt;/td&gt;&lt;td&gt;对索引执行范围扫描&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;index&lt;/code&gt;&lt;/td&gt;&lt;td&gt;扫描整个索引&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ALL&lt;/code&gt;&lt;/td&gt;&lt;td&gt;扫描整张表&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;分析时通常需要重点关注 &lt;code&gt;ALL&lt;/code&gt; 和 &lt;code&gt;index&lt;/code&gt;。不过小表全表扫描不一定是问题，不能只根据 &lt;code&gt;type&lt;/code&gt; 单独判断 SQL 是否需要优化。&lt;/p&gt;
&lt;h2&gt;索引相关列&lt;a href=&quot;#索引相关列&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;possible_keys&lt;/code&gt;&lt;a href=&quot;#possible_keys&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;显示优化器认为可能使用的索引。值为 &lt;code&gt;NULL&lt;/code&gt; 表示当前查询没有明显可用索引，但这并不等同于 SQL 一定存在性能问题。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;key&lt;/code&gt;&lt;a href=&quot;#key&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;显示优化器最终选择的索引。即使 &lt;code&gt;possible_keys&lt;/code&gt; 列出了多个索引，&lt;code&gt;key&lt;/code&gt; 通常也只显示实际采用的索引；使用 &lt;code&gt;index_merge&lt;/code&gt; 时可能显示多个索引。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;key_len&lt;/code&gt;&lt;a href=&quot;#key_len&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;显示执行计划预计使用的索引键长度。对于联合索引，可以根据该值辅助判断使用到了哪些索引列。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;key_len&lt;/code&gt; 是估算的最大长度，不代表实际读取的数据长度。字符集、可空列、变长字段和索引列类型都会影响该值。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;ref&lt;/code&gt;&lt;a href=&quot;#ref&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;显示索引查找时用于比较的值。例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;const&lt;/code&gt;：与常量比较。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;库名.表名.列名&lt;/code&gt;：与另一张表的列比较。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;func&lt;/code&gt;：与表达式、函数结果或发生类型转换的值比较。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;&lt;code&gt;rows&lt;/code&gt; 与 &lt;code&gt;filtered&lt;/code&gt;&lt;a href=&quot;#rows-与-filtered&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;rows&lt;/code&gt;&lt;a href=&quot;#rows&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;rows&lt;/code&gt; 是优化器估算需要检查的行数，并非实际扫描行数。统计信息不准确时，估算结果也可能出现偏差。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;filtered&lt;/code&gt;&lt;a href=&quot;#filtered&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;filtered&lt;/code&gt; 是预计通过当前表条件过滤后保留的数据比例，单位为百分比。&lt;/p&gt;
&lt;p&gt;可以用下面的方式粗略估算传递给下一步的行数：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;rows × filtered ÷ 100&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;若需要观察实际执行行数和耗时，应使用 &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;Extra&lt;/code&gt;：补充信息&lt;a href=&quot;#extra补充信息&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Extra&lt;/code&gt; 中常见信息如下：&lt;/p&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;信息&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Using index&lt;/code&gt;&lt;/td&gt;&lt;td&gt;使用覆盖索引即可获得所需列，通常不需要回表&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Using where&lt;/code&gt;&lt;/td&gt;&lt;td&gt;读取数据后还需要根据条件进行过滤&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Using index condition&lt;/code&gt;&lt;/td&gt;&lt;td&gt;使用索引条件下推，在存储引擎层过滤部分记录&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Using filesort&lt;/code&gt;&lt;/td&gt;&lt;td&gt;排序无法直接利用合适的索引，需要额外排序；不一定真的写磁盘文件&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Using temporary&lt;/code&gt;&lt;/td&gt;&lt;td&gt;使用内部临时表保存中间结果，常见于部分分组、去重或排序操作&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Using join buffer&lt;/code&gt;&lt;/td&gt;&lt;td&gt;连接过程使用连接缓冲区，通常需要检查连接条件和索引&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;FirstMatch&lt;/code&gt;&lt;/td&gt;&lt;td&gt;半连接优化策略之一，找到首个匹配后停止继续查找&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;LooseScan&lt;/code&gt;&lt;/td&gt;&lt;td&gt;半连接优化策略之一，通过索引跳跃扫描减少重复匹配&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;Impossible WHERE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;优化器判断查询条件不可能成立&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;code&gt;Extra&lt;/code&gt; 可以同时出现多项信息。例如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Using index condition; Using where&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;基本分析思路&lt;a href=&quot;#基本分析思路&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;分析执行计划时，可以按以下顺序检查：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;确认表的访问顺序是否合理。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;检查 &lt;code&gt;type&lt;/code&gt; 是否出现大表的 &lt;code&gt;ALL&lt;/code&gt; 或不必要的 &lt;code&gt;index&lt;/code&gt; 扫描。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对比 &lt;code&gt;possible_keys&lt;/code&gt; 与 &lt;code&gt;key&lt;/code&gt;，确认索引是否被选中。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;结合 &lt;code&gt;key_len&lt;/code&gt; 判断联合索引的使用范围。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;关注 &lt;code&gt;rows&lt;/code&gt;、&lt;code&gt;filtered&lt;/code&gt; 和 &lt;code&gt;Extra&lt;/code&gt; 中的排序、临时表及连接缓冲信息。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;对关键 SQL 使用 &lt;code&gt;EXPLAIN ANALYZE&lt;/code&gt;，以实际行数和耗时验证估算结果。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:mysql</category></item><item><title>商品管理 Demo</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/demo/shang-pin-guan-li-demo</link><guid isPermaLink="false">learn/hyxy/demo/shang-pin-guan-li-demo</guid><description>商品管理 Demo
本示例使用 Spring Boot、MyBatis-Plus、MySQL 和 Druid，实现商品与类别的分页关联查询。
一、准备数据库
创建 java2601 数据库，并导入 goods.sql 中的表结构和测试数据。示例至少需要以下两张表：

goods：商品表。</description><pubDate>Thu, 30 Jul 2026 12:15:31 GMT</pubDate><content:encoded>&lt;h1&gt;商品管理 Demo&lt;a href=&quot;#商品管理-demo&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;本示例使用 Spring Boot、&lt;code&gt;MyBatis-Plus&lt;/code&gt;、MySQL 和 Druid，实现商品与类别的分页关联查询。&lt;/p&gt;
&lt;h2&gt;一、准备数据库&lt;a href=&quot;#一准备数据库&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;创建 &lt;code&gt;java2601&lt;/code&gt; 数据库，并导入 &lt;code&gt;goods.sql&lt;/code&gt; 中的表结构和测试数据。示例至少需要以下两张表：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;goods&lt;/code&gt;：商品表。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;category&lt;/code&gt;：商品类别表。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;商品表中的 &lt;code&gt;cid&lt;/code&gt; 用于关联类别表的 &lt;code&gt;cid&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;二、创建 Spring Boot 工程&lt;a href=&quot;#二创建-spring-boot-工程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;引入依赖&lt;a href=&quot;#引入依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 &lt;code&gt;pom.xml&lt;/code&gt; 中加入以下依赖。版本号可根据课程项目的 Spring Boot 版本统一管理。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-web&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.baomidou&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-plus-spring-boot3-starter&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.5.6&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;runtime&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.alibaba&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;druid-spring-boot-3-starter&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.2.23&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.projectlombok&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;lombok&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;gt;true&amp;lt;/&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-devtools&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;gt;true&amp;lt;/&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-test&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;test&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;配置数据源和 &lt;code&gt;MyBatis-Plus&lt;/code&gt;&lt;a href=&quot;#配置数据源和-mybatis-plus&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 &lt;code&gt;application.yml&lt;/code&gt; 中配置数据库连接和 &lt;code&gt;MyBatis-Plus&lt;/code&gt;：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;spring&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  datasource&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;com.alibaba.druid.pool.DruidDataSource&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    druid&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      url&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;jdbc:mysql://localhost:3306/java2601?useUnicode=true&amp;amp;characterEncoding=utf8&amp;amp;serverTimezone=Asia/Shanghai&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      username&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      password&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      driver-class-name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;com.mysql.cj.jdbc.Driver&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      initial-size&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      min-idle&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      max-active&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      max-wait&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;10000&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mybatis-plus&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  mapper-locations&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;classpath*:/mapper/**/*.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  type-aliases-package&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;com.hyxy.goods.po&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  configuration&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    map-underscore-to-camel-case&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    log-impl&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;org.apache.ibatis.logging.stdout.StdOutImpl&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  global-config&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    db-config&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      id-type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      # table-prefix: tb_&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      # logic-delete-field: deleteFlag&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      # logic-delete-value: 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      # logic-not-delete-value: 0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;开发环境可以直接写用户名和密码，实际项目应通过环境变量或外部配置管理数据库凭据。&lt;/p&gt;
&lt;h3&gt;创建目录结构&lt;a href=&quot;#创建目录结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;建议按照控制器、业务层、数据访问层和实体类分包。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730201510980.png&quot; alt=&quot;image-001&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-001&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;使用逆向工程生成基础代码&lt;a href=&quot;#使用逆向工程生成基础代码&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;可以使用 &lt;code&gt;MyBatis-Plus&lt;/code&gt; 代码生成器生成实体类、Mapper、Service 和对应 XML 文件。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730201512943.png&quot; alt=&quot;image-002&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-002&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;生成后需要检查包名、表名、主键策略以及生成文件的保存位置，不能直接假定所有配置都符合当前项目。&lt;/p&gt;
&lt;h2&gt;三、扫描 Mapper 接口&lt;a href=&quot;#三扫描-mapper-接口&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;在启动类上使用 &lt;code&gt;@MapperScan&lt;/code&gt;，统一扫描 Mapper 接口：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.hyxy.goods;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.mybatis.spring.annotation.MapperScan;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.boot.SpringApplication;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.boot.autoconfigure.SpringBootApplication;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;SpringBootApplication&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;MapperScan&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.goods.mapper&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; GoodsApplication&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SpringApplication.&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;(GoodsApplication.class, args);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;使用 &lt;code&gt;@MapperScan&lt;/code&gt; 后，通常不需要再在每个 Mapper 接口上添加 &lt;code&gt;@Mapper&lt;/code&gt;。两种方式选择一种即可。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.hyxy.goods.mapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.core.mapper.BaseMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.hyxy.goods.po.Category;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; CategoryMapper&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; BaseMapper&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Category&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.hyxy.goods.mapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.core.mapper.BaseMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.hyxy.goods.po.Goods;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; GoodsMapper&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; BaseMapper&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Goods&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;四、配置分页插件&lt;a href=&quot;#四配置分页插件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;在 &lt;code&gt;config&lt;/code&gt; 包中创建配置类，并注册 &lt;code&gt;MyBatis-Plus&lt;/code&gt; 分页拦截器：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.hyxy.goods.config;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.annotation.DbType;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.context.annotation.Bean;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.context.annotation.Configuration;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MybatisPlusConfig&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; MybatisPlusInterceptor &lt;/span&gt;&lt;span&gt;mybatisPlusInterceptor&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        MybatisPlusInterceptor interceptor &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; MybatisPlusInterceptor&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        interceptor.&lt;/span&gt;&lt;span&gt;addInnerInterceptor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; PaginationInnerInterceptor&lt;/span&gt;&lt;span&gt;(DbType.MYSQL));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; interceptor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;本课件使用 &lt;code&gt;MyBatis-Plus&lt;/code&gt; &lt;code&gt;3.5.6&lt;/code&gt;。若升级到 &lt;code&gt;3.5.9&lt;/code&gt; 或更高版本，分页插件相关解析器已拆分为可选依赖，需要按照对应版本的官方说明补充模块。&lt;/p&gt;
&lt;h2&gt;五、实现商品与类别的关联查询&lt;a href=&quot;#五实现商品与类别的关联查询&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;查询商品时，同时显示所属类别名称。&lt;/p&gt;
&lt;h3&gt;在商品实体类中添加非表字段&lt;a href=&quot;#在商品实体类中添加非表字段&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;cname&lt;/code&gt; 来自关联查询，不是 &lt;code&gt;goods&lt;/code&gt; 表中的真实字段，因此需要使用 &lt;code&gt;@TableField(exist = false)&lt;/code&gt;：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.hyxy.goods.po;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.annotation.TableField;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; lombok.Data;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Goods&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 省略 goods 表中的其他字段&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;exist&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String cname;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;在 Mapper 接口中声明查询方法&lt;a href=&quot;#在-mapper-接口中声明查询方法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;分页参数应放在方法参数列表前面，查询条件使用 &lt;code&gt;@Param&lt;/code&gt; 显式命名：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.hyxy.goods.mapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.core.mapper.BaseMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.core.metadata.IPage;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.extension.plugins.pagination.Page;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.hyxy.goods.po.Goods;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.annotations.Param;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; GoodsMapper&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; BaseMapper&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Goods&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    IPage&amp;lt;&lt;/span&gt;&lt;span&gt;Goods&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;selectJoinCategory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Page&amp;lt;&lt;/span&gt;&lt;span&gt;Goods&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;Param&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;gname&quot;&lt;/span&gt;&lt;span&gt;) String &lt;/span&gt;&lt;span&gt;gname&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;Param&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;cid&quot;&lt;/span&gt;&lt;span&gt;) Integer &lt;/span&gt;&lt;span&gt;cid&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;编写 Mapper XML&lt;a href=&quot;#编写-mapper-xml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 &lt;code&gt;resources/mapper&lt;/code&gt; 目录下创建 &lt;code&gt;GoodsMapper.xml&lt;/code&gt;。&lt;code&gt;namespace&lt;/code&gt; 必须与 Mapper 接口的全限定类名一致。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;?&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span&gt; encoding&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt; ?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!&lt;/span&gt;&lt;span&gt;DOCTYPE&lt;/span&gt;&lt;span&gt; mapper&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        PUBLIC &quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;https://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt; namespace&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.goods.mapper.GoodsMapper&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectJoinCategory&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Goods&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            g.gid,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            g.gname,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            g.price,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            g.stock,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            g.cid,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            g.sales,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            g.onsale,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            g.createtime,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            c.cname AS cname&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        FROM goods AS g&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        LEFT JOIN category AS c ON g.cid = c.cid&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;gname != null and gname != &apos;&apos;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                AND g.gname LIKE CONCAT(&apos;%&apos;, #{gname}, &apos;%&apos;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;cid != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                AND g.cid = #{cid}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        ORDER BY g.gid DESC&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;关联查询中的列应尽量添加表别名，避免两张表存在同名字段时产生歧义。&lt;/p&gt;
&lt;h2&gt;六、编写测试&lt;a href=&quot;#六编写测试&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;使用 Spring Boot 测试类验证分页和关联查询结果：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.hyxy.goods;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.core.metadata.IPage;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.extension.plugins.pagination.Page;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.hyxy.goods.mapper.GoodsMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.hyxy.goods.po.Goods;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; jakarta.annotation.Resource;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.junit.jupiter.api.Test;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.boot.test.context.SpringBootTest;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;SpringBootTest&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; GoodsApplicationTests&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Resource&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; GoodsMapper goodsMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    void&lt;/span&gt;&lt;span&gt; selectJoinCategory&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Page&amp;lt;&lt;/span&gt;&lt;span&gt;Goods&lt;/span&gt;&lt;span&gt;&amp;gt; page &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Page&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        IPage&amp;lt;&lt;/span&gt;&lt;span&gt;Goods&lt;/span&gt;&lt;span&gt;&amp;gt; pageResult &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; goodsMapper.&lt;/span&gt;&lt;span&gt;selectJoinCategory&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                page,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                null&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        pageResult.&lt;/span&gt;&lt;span&gt;getRecords&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;forEach&lt;/span&gt;&lt;span&gt;(System.out&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;println);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;总记录数：&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; pageResult.&lt;/span&gt;&lt;span&gt;getTotal&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;总页数：&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; pageResult.&lt;/span&gt;&lt;span&gt;getPages&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;测试时应确认控制台生成了带分页限制的 SQL，并检查每个商品对象中的 &lt;code&gt;cname&lt;/code&gt; 是否正确映射。&lt;/p&gt;
&lt;h2&gt;七、常见问题&lt;a href=&quot;#七常见问题&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Mapper 方法找不到对应 SQL&lt;a href=&quot;#mapper-方法找不到对应-sql&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;检查以下内容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;XML 的 &lt;code&gt;namespace&lt;/code&gt; 是否与 Mapper 接口全限定名一致。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;select&amp;gt;&lt;/code&gt; 的 &lt;code&gt;id&lt;/code&gt; 是否与接口方法名一致。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mapper-locations&lt;/code&gt; 是否覆盖 XML 文件所在目录。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;分页不生效&lt;a href=&quot;#分页不生效&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;确认已经注册 &lt;code&gt;MybatisPlusInterceptor&lt;/code&gt; 和 &lt;code&gt;PaginationInnerInterceptor&lt;/code&gt;，并保证分页参数位于 Mapper 方法参数列表前面。&lt;/p&gt;
&lt;h3&gt;类别编号条件报错或查询结果异常&lt;a href=&quot;#类别编号条件报错或查询结果异常&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在多表查询中使用 &lt;code&gt;g.cid&lt;/code&gt;，不要直接写没有表别名的 &lt;code&gt;cid&lt;/code&gt;，否则可能出现字段歧义。&lt;/p&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:demo</category><category>tag:demo</category></item><item><title>Knife4j 实战</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/tools/knife4j-shi-zhan</link><guid isPermaLink="false">learn/hyxy/tools/knife4j-shi-zhan</guid><description>Knife4j 实战
Knife4j 核心认知
什么是 Knife4j
Knife4j 是面向 Java Web 项目的接口文档增强解决方案。它能够读取应用生成的 OpenAPI 文档，并提供更易用的接口展示、在线调试、搜索、排序、离线导出和访问控制等功能。
在 Spring Boot 3</description><pubDate>Thu, 30 Jul 2026 11:37:51 GMT</pubDate><content:encoded>&lt;h1&gt;Knife4j 实战&lt;a href=&quot;#knife4j-实战&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;Knife4j 核心认知&lt;a href=&quot;#knife4j-核心认知&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;什么是 Knife4j&lt;a href=&quot;#什么是-knife4j&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Knife4j 是面向 Java Web 项目的接口文档增强解决方案。它能够读取应用生成的 OpenAPI 文档，并提供更易用的接口展示、在线调试、搜索、排序、离线导出和访问控制等功能。&lt;/p&gt;
&lt;p&gt;在 Spring Boot 3 项目中，可以将相关组件理解为以下关系：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OpenAPI 3&lt;/strong&gt;：描述 RESTful API 的规范。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;springdoc-openapi&lt;/strong&gt;：扫描 Spring Web 接口并生成 OpenAPI 3 文档。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Swagger UI&lt;/strong&gt;：展示和调试 OpenAPI 文档的通用 Web 界面。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Knife4j&lt;/strong&gt;：在 OpenAPI 文档基础上提供增强界面和扩展能力。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此，Knife4j 不是一种新的接口规范，也不等同于 OpenAPI 3。对于 Spring Boot 3 项目，Knife4j 的底层文档生成能力主要由 &lt;code&gt;springdoc-openapi&lt;/code&gt; 提供。&lt;/p&gt;
&lt;h3&gt;Spring Boot 2 与 Spring Boot 3 的主要差异&lt;a href=&quot;#spring-boot-2-与-spring-boot-3-的主要差异&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;对比项&lt;/th&gt;&lt;th&gt;Spring Boot 2 常见方案&lt;/th&gt;&lt;th&gt;Spring Boot 3 推荐方案&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Java 版本&lt;/td&gt;&lt;td&gt;通常可以使用 JDK 8 或更高版本，具体取决于 Spring Boot 版本&lt;/td&gt;&lt;td&gt;最低需要 JDK 17&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Java EE 包名&lt;/td&gt;&lt;td&gt;主要使用 &lt;code&gt;javax.*&lt;/code&gt;&lt;/td&gt;&lt;td&gt;迁移到 &lt;code&gt;jakarta.*&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;接口文档规范&lt;/td&gt;&lt;td&gt;可以使用 OpenAPI 2 或 OpenAPI 3&lt;/td&gt;&lt;td&gt;推荐使用 OpenAPI 3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;常见实现&lt;/td&gt;&lt;td&gt;Springfox 或 springdoc-openapi&lt;/td&gt;&lt;td&gt;springdoc-openapi&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Knife4j Starter&lt;/td&gt;&lt;td&gt;根据规范和框架版本选择对应 Starter&lt;/td&gt;&lt;td&gt;使用 Jakarta 版本的 OpenAPI 3 Starter&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;常用注解&lt;/td&gt;&lt;td&gt;旧项目可能使用 &lt;code&gt;io.swagger.annotations.*&lt;/code&gt;&lt;/td&gt;&lt;td&gt;使用 &lt;code&gt;io.swagger.v3.oas.annotations.*&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：并不是 Spring Boot 3 本身“废弃了 Swagger 2 注解”，而是 Spring Boot 3 项目通常不再使用基于 Springfox 的旧方案。迁移到 &lt;code&gt;springdoc-openapi&lt;/code&gt; 后，应将旧注解替换为 OpenAPI 3 注解。&lt;/p&gt;
&lt;h3&gt;Knife4j 相比 Swagger UI 的常见增强&lt;a href=&quot;#knife4j-相比-swagger-ui-的常见增强&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;对比项&lt;/th&gt;&lt;th&gt;Swagger UI&lt;/th&gt;&lt;th&gt;Knife4j&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;页面展示&lt;/td&gt;&lt;td&gt;提供标准 OpenAPI 文档界面&lt;/td&gt;&lt;td&gt;提供更适合中文项目的增强界面&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;接口调试&lt;/td&gt;&lt;td&gt;支持在线发送请求&lt;/td&gt;&lt;td&gt;增强参数填写、请求调试和结果展示&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;接口检索&lt;/td&gt;&lt;td&gt;支持基础过滤&lt;/td&gt;&lt;td&gt;提供接口搜索等增强功能&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;文档导出&lt;/td&gt;&lt;td&gt;默认不提供完整的离线导出流程&lt;/td&gt;&lt;td&gt;支持导出 Markdown、HTML、Word 和 OpenAPI 文档&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;扩展配置&lt;/td&gt;&lt;td&gt;使用 Swagger UI 配置项&lt;/td&gt;&lt;td&gt;额外提供 Knife4j 增强配置&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;访问保护&lt;/td&gt;&lt;td&gt;通常需要自行结合安全框架处理&lt;/td&gt;&lt;td&gt;提供生产保护和 Basic 认证等辅助配置&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;适用场景&lt;a href=&quot;#适用场景&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;前后端分离项目中自动生成并维护接口文档。&lt;/li&gt;
&lt;li&gt;开发和测试阶段在线调用接口。&lt;/li&gt;
&lt;li&gt;展示请求参数、响应结构、状态码和字段说明。&lt;/li&gt;
&lt;li&gt;多模块或微服务项目中统一管理接口文档。&lt;/li&gt;
&lt;li&gt;将接口文档导出后用于交付或归档。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Spring Boot 3 集成 Knife4j&lt;a href=&quot;#spring-boot-3-集成-knife4j&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;环境要求&lt;a href=&quot;#环境要求&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;本文示例采用以下环境：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;JDK 17 或更高版本。&lt;/li&gt;
&lt;li&gt;Spring Boot 3.x。&lt;/li&gt;
&lt;li&gt;Maven 项目。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spring-boot-starter-web&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;Knife4j 4.5.0。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;实际项目中应根据 Spring Boot 的具体版本检查依赖兼容性，不要仅凭“版本更高”判断组件一定兼容。&lt;/p&gt;
&lt;h3&gt;引入 Maven 依赖&lt;a href=&quot;#引入-maven-依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Spring Boot 3 使用 Jakarta 版本的 Knife4j Starter：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.github.xiaoymin&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;knife4j-openapi3-jakarta-spring-boot-starter&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;4.5.0&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;该 Starter 已经集成 OpenAPI 3 所需的 springdoc-openapi 相关依赖。通常不需要再单独引入 Springfox、Swagger 2 或其他版本的 springdoc-openapi，否则可能产生依赖冲突。&lt;/p&gt;
&lt;h3&gt;配置 application.yml&lt;a href=&quot;#配置-applicationyml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;下面给出一个适合单模块项目的基础配置：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  port&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;8080&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;spring&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  application&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;knife4j-spring-boot3-demo&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;springdoc&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  swagger-ui&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    path&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/swagger-ui.html&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    tags-sorter&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;alpha&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    operations-sorter&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;alpha&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  api-docs&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    path&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/v3/api-docs&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  group-configs&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - &lt;/span&gt;&lt;span&gt;group&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      paths-to-match&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      packages-to-scan&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;com.example.knife4jdemo.controller&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;knife4j&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enable&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  setting&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    language&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;zh_cn&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;配置说明：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;springdoc.api-docs.path&lt;/code&gt; 用于配置 OpenAPI JSON 文档地址。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;springdoc.group-configs&lt;/code&gt; 用于配置文档分组、接口路径和控制器扫描包。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;packages-to-scan&lt;/code&gt; 必须替换为当前项目实际的控制器包名。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;knife4j.enable&lt;/code&gt; 用于开启 Knife4j 增强功能。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;knife4j.setting.language&lt;/code&gt; 用于设置界面语言。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;配置接口文档基本信息&lt;a href=&quot;#配置接口文档基本信息&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;通过声明 &lt;code&gt;OpenAPI&lt;/code&gt; Bean 可以统一设置文档标题、版本、说明和联系信息：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.example.knife4jdemo.config;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.models.OpenAPI;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.models.info.Contact;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.models.info.Info;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.models.info.License;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.context.annotation.Bean;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.context.annotation.Configuration;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Knife4jOpenApiConfig&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; OpenAPI &lt;/span&gt;&lt;span&gt;customOpenAPI&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; OpenAPI&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;info&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; Info&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;用户管理系统接口文档&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;1.0.0&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;基于 Spring Boot 3、OpenAPI 3 和 Knife4j 构建的接口文档&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;contact&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; Contact&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                .&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;项目开发组&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                .&lt;/span&gt;&lt;span&gt;email&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;demo@example.com&quot;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;license&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; License&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                .&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Apache 2.0&quot;&lt;/span&gt;&lt;span&gt;)));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;启动项目并访问文档&lt;a href=&quot;#启动项目并访问文档&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;启动 Spring Boot 项目后，在浏览器中访问：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;http://localhost:8080/doc.html&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;OpenAPI JSON 文档的默认访问地址为 &lt;code&gt;/v3/api-docs&lt;/code&gt;。如果配置了分组，还可能生成对应的分组文档地址。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;doc.html&lt;/code&gt; 无法访问时的排查顺序&lt;a href=&quot;#dochtml-无法访问时的排查顺序&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;正常情况下，引入 Starter 后不需要手动配置静态资源映射。如果出现 &lt;code&gt;404&lt;/code&gt;、&lt;code&gt;401&lt;/code&gt; 或 &lt;code&gt;403&lt;/code&gt;，应按照以下顺序排查：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;检查 Maven 依赖是否使用了 Spring Boot 3 对应的 Jakarta Starter。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;检查项目是否错误引入了多个 springdoc-openapi 或 Springfox 版本。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;检查 &lt;code&gt;packages-to-scan&lt;/code&gt; 是否为真实的控制器包路径。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;检查项目是否使用了 &lt;code&gt;@EnableWebMvc&lt;/code&gt;，或者是否完全接管了 Spring MVC 配置。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;检查 Spring Security 是否拦截了文档页面和 OpenAPI 文档接口。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;检查应用是否配置了 &lt;code&gt;context-path&lt;/code&gt;，访问地址是否需要增加上下文路径。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;只有在项目确实自定义了静态资源规则，并确认自动配置没有生效时，才考虑补充资源映射：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.example.knife4jdemo.config;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.context.annotation.Configuration;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.servlet.config.annotation.WebMvcConfigurer;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; WebResourceConfig&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; WebMvcConfigurer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; addResourceHandlers&lt;/span&gt;&lt;span&gt;(ResourceHandlerRegistry &lt;/span&gt;&lt;span&gt;registry&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        registry.&lt;/span&gt;&lt;span&gt;addResourceHandler&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/doc.html&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;addResourceLocations&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;classpath:/META-INF/resources/&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        registry.&lt;/span&gt;&lt;span&gt;addResourceHandler&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/webjars/**&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;addResourceLocations&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;classpath:/META-INF/resources/webjars/&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;这段配置属于故障排查方案，不是所有 Spring Boot 3 项目的固定必配项。&lt;/p&gt;
&lt;h2&gt;OpenAPI 3 常用注解&lt;a href=&quot;#openapi-3-常用注解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;旧注解与新注解对照&lt;a href=&quot;#旧注解与新注解对照&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;













































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;功能&lt;/th&gt;&lt;th&gt;旧版 Swagger 2 注解&lt;/th&gt;&lt;th&gt;OpenAPI 3 注解&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;控制器分组&lt;/td&gt;&lt;td&gt;&lt;code&gt;@Api&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;@Tag&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;接口说明&lt;/td&gt;&lt;td&gt;&lt;code&gt;@ApiOperation&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;@Operation&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;参数说明&lt;/td&gt;&lt;td&gt;&lt;code&gt;@ApiParam&lt;/code&gt;、&lt;code&gt;@ApiImplicitParam&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;@Parameter&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;多个参数说明&lt;/td&gt;&lt;td&gt;&lt;code&gt;@ApiImplicitParams&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;@Parameters&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;模型说明&lt;/td&gt;&lt;td&gt;&lt;code&gt;@ApiModel&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;@Schema&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;字段说明&lt;/td&gt;&lt;td&gt;&lt;code&gt;@ApiModelProperty&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;@Schema&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;隐藏接口或类&lt;/td&gt;&lt;td&gt;&lt;code&gt;@ApiIgnore&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;@Hidden&lt;/code&gt; 或 &lt;code&gt;@Operation(hidden = true)&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;使用 &lt;code&gt;@Schema&lt;/code&gt; 描述实体类&lt;a href=&quot;#使用-schema-描述实体类&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.example.knife4jdemo.domain;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.annotations.media.Schema;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;用户信息&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; User&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;用户主键&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            requiredMode&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Schema.RequiredMode.REQUIRED,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            example&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;10001&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Long id;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;用户名&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            requiredMode&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Schema.RequiredMode.REQUIRED,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            example&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;zhangsan&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String username;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;手机号码&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            requiredMode&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Schema.RequiredMode.REQUIRED,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            example&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;13800138000&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String phone;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;年龄&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;26&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer age;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;用户状态：0 表示禁用，1 表示正常&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;1&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer status;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Long &lt;/span&gt;&lt;span&gt;getId&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; id;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setId&lt;/span&gt;&lt;span&gt;(Long &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.id &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; id;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;getUsername&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; username;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setUsername&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;username&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.username &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; username;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;getPhone&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; phone;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setPhone&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;phone&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.phone &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; phone;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Integer &lt;/span&gt;&lt;span&gt;getAge&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; age;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setAge&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;age&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.age &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; age;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Integer &lt;/span&gt;&lt;span&gt;getStatus&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; status;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setStatus&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.status &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; status;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;使用 Lombok 的项目可以通过 &lt;code&gt;@Data&lt;/code&gt; 简化 Getter 和 Setter，但需要确保项目已经正确引入 Lombok 并启用注解处理。&lt;/p&gt;
&lt;h3&gt;使用 &lt;code&gt;@Tag&lt;/code&gt; 和 &lt;code&gt;@Operation&lt;/code&gt; 描述控制器&lt;a href=&quot;#使用-tag-和-operation-描述控制器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.example.knife4jdemo.controller;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.example.knife4jdemo.domain.User;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.annotations.Operation;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.annotations.Parameter;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.annotations.tags.Tag;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.GetMapping;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.PathVariable;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.RequestMapping;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.RestController;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequestMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/users&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Tag&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;用户管理&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;提供用户查询接口&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; UserController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/{id}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;根据编号查询用户&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;根据用户主键查询用户详细信息&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; User &lt;/span&gt;&lt;span&gt;getUserById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;Parameter&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;用户主键&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    required&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    example&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;10001&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;PathVariable&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;id&quot;&lt;/span&gt;&lt;span&gt;) Long &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        User user &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; User&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        user.&lt;/span&gt;&lt;span&gt;setId&lt;/span&gt;&lt;span&gt;(id);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        user.&lt;/span&gt;&lt;span&gt;setUsername&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;zhangsan&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        user.&lt;/span&gt;&lt;span&gt;setPhone&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;13800138000&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        user.&lt;/span&gt;&lt;span&gt;setAge&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;26&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        user.&lt;/span&gt;&lt;span&gt;setStatus&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; user;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;查询用户列表&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;查询当前系统中的用户数据&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;User&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;listUsers&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; List.&lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;getUserById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10001L&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;重启项目后访问：&lt;/p&gt;
&lt;p&gt;&lt;code&gt;http://localhost:8080/doc.html&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;页面中应展示用户管理分组、接口摘要、参数说明和响应模型。&lt;/p&gt;
&lt;h2&gt;Knife4j 进阶功能&lt;a href=&quot;#knife4j-进阶功能&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;配置全局 JWT 认证&lt;a href=&quot;#配置全局-jwt-认证&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;对于使用 JWT 的项目，可以在 OpenAPI 文档中声明 HTTP Bearer 认证方案。下面的配置是前面 &lt;code&gt;OpenAPI&lt;/code&gt; Bean 的升级版本，实际项目中只保留一个 &lt;code&gt;OpenAPI&lt;/code&gt; Bean：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.example.knife4jdemo.config;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.models.Components;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.models.OpenAPI;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.models.info.Contact;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.models.info.Info;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.models.info.License;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.models.security.SecurityRequirement;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.models.security.SecurityScheme;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.context.annotation.Bean;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.context.annotation.Configuration;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Knife4jOpenApiConfig&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; String SECURITY_SCHEME_NAME &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;BearerAuth&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; OpenAPI &lt;/span&gt;&lt;span&gt;customOpenAPI&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SecurityScheme securityScheme &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; SecurityScheme&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;(SecurityScheme.Type.HTTP)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;scheme&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;bearer&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;bearerFormat&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;JWT&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;输入登录后获得的 JWT&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; OpenAPI&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;info&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; Info&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;用户管理系统接口文档&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;1.0.0&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;支持 JWT 调试的接口文档&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;contact&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; Contact&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                .&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;项目开发组&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                .&lt;/span&gt;&lt;span&gt;email&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;demo@example.com&quot;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;license&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; License&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                .&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Apache 2.0&quot;&lt;/span&gt;&lt;span&gt;)))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;components&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; Components&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;addSecuritySchemes&lt;/span&gt;&lt;span&gt;(SECURITY_SCHEME_NAME, securityScheme))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;addSecurityItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; SecurityRequirement&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        .&lt;/span&gt;&lt;span&gt;addList&lt;/span&gt;&lt;span&gt;(SECURITY_SCHEME_NAME));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;配置完成后，文档页面会显示认证入口。开发人员输入 JWT 后，调试请求会按照 Bearer 认证方式携带 &lt;code&gt;Authorization&lt;/code&gt; 请求头。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：将安全方案添加到 &lt;code&gt;OpenAPI&lt;/code&gt; 对象表示文档默认要求认证，但它不会替代 Spring Security 的服务端鉴权逻辑。&lt;/p&gt;
&lt;h3&gt;导出离线文档&lt;a href=&quot;#导出离线文档&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Knife4j 的文档管理功能可以导出以下内容：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Markdown 文档。&lt;/li&gt;
&lt;li&gt;离线 HTML 文档。&lt;/li&gt;
&lt;li&gt;Word 文档。&lt;/li&gt;
&lt;li&gt;原始 OpenAPI JSON 文档。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Knife4j 官方导出功能不直接生成 PDF。需要 PDF 时，可以先导出 Markdown 或 HTML，再使用其他工具转换为 PDF。&lt;/p&gt;
&lt;h3&gt;隐藏不需要展示的接口&lt;a href=&quot;#隐藏不需要展示的接口&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用 &lt;code&gt;@Hidden&lt;/code&gt; 可以隐藏控制器或接口：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.example.knife4jdemo.controller;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.annotations.Hidden;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.PostMapping;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.RequestMapping;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.RestController;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Hidden&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequestMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/admin&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; AdminController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PostMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/password&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;updatePassword&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; &quot;密码修改成功&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;也可以只隐藏单个方法：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Hidden&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;PostMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/internal/reset&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;resetData&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; &quot;重置成功&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;重要说明&lt;/strong&gt;：&lt;code&gt;@Hidden&lt;/code&gt; 只控制接口是否出现在 OpenAPI 文档中，不会阻止客户端访问该接口。敏感接口仍然必须通过 Spring Security、权限校验和网关策略进行保护。&lt;/p&gt;
&lt;h2&gt;生产环境安全配置&lt;a href=&quot;#生产环境安全配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;开发环境配置&lt;a href=&quot;#开发环境配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;开发环境可以开启接口文档：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;knife4j&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enable&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  production&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;生产环境关闭文档&lt;a href=&quot;#生产环境关闭文档&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;生产环境可以同时关闭 Knife4j 页面、Swagger UI 和 OpenAPI JSON 接口：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;springdoc&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  api-docs&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    enabled&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  swagger-ui&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    enabled&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;knife4j&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enable&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  production&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;其中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;knife4j.production&lt;/code&gt; 用于开启 Knife4j 的生产环境保护策略。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;springdoc.api-docs.enabled&lt;/code&gt; 用于关闭 OpenAPI JSON 接口。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;springdoc.swagger-ui.enabled&lt;/code&gt; 用于关闭 Swagger UI。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;生产环境是否完全禁用接口文档，应根据项目的网络隔离、权限模型和运维要求决定。&lt;/p&gt;
&lt;h3&gt;使用 Basic 认证保护文档&lt;a href=&quot;#使用-basic-认证保护文档&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在内部测试环境确实需要开放文档时，可以启用 Basic 认证：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;knife4j&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  enable&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  production&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  basic&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    enable&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    username&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;doc_user&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    password&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;${KNIFE4J_PASSWORD}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不要在代码仓库中直接保存真实密码。示例使用环境变量 &lt;code&gt;KNIFE4J_PASSWORD&lt;/code&gt; 注入密码。&lt;/p&gt;
&lt;p&gt;Basic 认证只能作为文档访问保护的一部分。生产系统还应结合 HTTPS、网络访问控制、Spring Security 和统一身份认证等措施。&lt;/p&gt;
&lt;h2&gt;常见问题&lt;a href=&quot;#常见问题&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;页面能够打开，但没有接口&lt;a href=&quot;#页面能够打开但没有接口&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;重点检查：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;packages-to-scan&lt;/code&gt; 是否配置正确。&lt;/li&gt;
&lt;li&gt;控制器是否使用了 &lt;code&gt;@RestController&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;请求方法是否使用了 &lt;code&gt;@GetMapping&lt;/code&gt;、&lt;code&gt;@PostMapping&lt;/code&gt; 等映射注解。&lt;/li&gt;
&lt;li&gt;控制器是否位于 Spring Boot 默认扫描范围内。&lt;/li&gt;
&lt;li&gt;是否错误配置了 &lt;code&gt;paths-to-match&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;文档页面返回 &lt;code&gt;401&lt;/code&gt; 或 &lt;code&gt;403&lt;/code&gt;&lt;a href=&quot;#文档页面返回-401-或-403&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;这通常表示请求被安全过滤器拦截。需要在开发环境中按需放行以下资源：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/doc.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/webjars/**&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/v3/api-docs/**&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/swagger-ui/**&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/swagger-ui.html&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;是否放行以及如何放行，应以项目实际使用的 Spring Security 版本和权限策略为准。&lt;/p&gt;
&lt;h3&gt;文档页面返回 &lt;code&gt;404&lt;/code&gt;&lt;a href=&quot;#文档页面返回-404&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;重点检查：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Starter 是否选择正确。&lt;/li&gt;
&lt;li&gt;依赖是否下载成功。&lt;/li&gt;
&lt;li&gt;是否存在依赖冲突。&lt;/li&gt;
&lt;li&gt;是否配置了应用上下文路径。&lt;/li&gt;
&lt;li&gt;是否使用 &lt;code&gt;@EnableWebMvc&lt;/code&gt; 覆盖了自动配置。&lt;/li&gt;
&lt;li&gt;是否自定义了静态资源映射。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;注解没有显示在文档中&lt;a href=&quot;#注解没有显示在文档中&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;检查注解导包是否来自 &lt;code&gt;io.swagger.v3.oas.annotations&lt;/code&gt;。不要混用旧版 &lt;code&gt;io.swagger.annotations&lt;/code&gt; 和 OpenAPI 3 注解。&lt;/p&gt;
&lt;h3&gt;修改接口后文档没有变化&lt;a href=&quot;#修改接口后文档没有变化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;可以依次尝试：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;确认代码已经重新编译并重启应用。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;刷新浏览器页面。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;清除 Knife4j 页面缓存。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;检查当前查看的是否为正确分组。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;直接访问 &lt;code&gt;/v3/api-docs&lt;/code&gt;，确认后端生成的 OpenAPI JSON 是否已经更新。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;总结&lt;a href=&quot;#总结&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Spring Boot 3 集成 Knife4j 的核心流程如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;使用 JDK 17 或更高版本。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;引入 Jakarta 版本的 Knife4j OpenAPI 3 Starter。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过 &lt;code&gt;springdoc&lt;/code&gt; 配置扫描包、分组和 OpenAPI 文档路径。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过 &lt;code&gt;OpenAPI&lt;/code&gt; Bean 设置文档基本信息和认证方案。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;使用 &lt;code&gt;@Tag&lt;/code&gt;、&lt;code&gt;@Operation&lt;/code&gt;、&lt;code&gt;@Parameter&lt;/code&gt; 和 &lt;code&gt;@Schema&lt;/code&gt; 描述接口。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;在开发环境开放文档，在生产环境按安全要求关闭或限制访问。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;明确区分“隐藏接口文档”和“保护真实接口”，不能将 &lt;code&gt;@Hidden&lt;/code&gt; 当作权限控制手段。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:工具</category><category>tag:Knife4j</category></item><item><title>Spring 事务管理</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/framework/spring-shi-wu-guan-li</link><guid isPermaLink="false">learn/hyxy/framework/spring-shi-wu-guan-li</guid><description>Spring 事务管理
Spring 事务管理相关接口的关系如下：
image-001
事务管理概述
Spring 为 JDBC、JPA、Hibernate、JTA 等不同数据访问技术提供统一的事务编程模型。业务代码主要面向 Spring</description><pubDate>Thu, 30 Jul 2026 11:36:45 GMT</pubDate><content:encoded>&lt;h1&gt;Spring 事务管理&lt;a href=&quot;#spring-事务管理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Spring 事务管理相关接口的关系如下：&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730193616054.png&quot; alt=&quot;image-001&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-001&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;事务管理概述&lt;a href=&quot;#事务管理概述&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Spring 为 JDBC、JPA、Hibernate、JTA 等不同数据访问技术提供统一的事务编程模型。业务代码主要面向 Spring 的事务抽象，而具体的提交、回滚和资源管理由相应事务管理器完成。&lt;/p&gt;
&lt;p&gt;核心接口是 &lt;code&gt;PlatformTransactionManager&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; PlatformTransactionManager&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; TransactionManager&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    TransactionStatus &lt;/span&gt;&lt;span&gt;getTransaction&lt;/span&gt;&lt;span&gt;(TransactionDefinition &lt;/span&gt;&lt;span&gt;definition&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            throws&lt;/span&gt;&lt;span&gt; TransactionException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    void&lt;/span&gt;&lt;span&gt; commit&lt;/span&gt;&lt;span&gt;(TransactionStatus &lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; TransactionException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    void&lt;/span&gt;&lt;span&gt; rollback&lt;/span&gt;&lt;span&gt;(TransactionStatus &lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; TransactionException;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;getTransaction()&lt;/code&gt; 根据事务定义获取当前事务状态；&lt;code&gt;commit()&lt;/code&gt; 和 &lt;code&gt;rollback()&lt;/code&gt; 分别负责提交与回滚。&lt;/p&gt;
&lt;h2&gt;常见事务管理器&lt;a href=&quot;#常见事务管理器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;JDBC 事务&lt;a href=&quot;#jdbc-事务&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用 JDBC 或 &lt;code&gt;JdbcTemplate&lt;/code&gt; 时，通常使用 &lt;code&gt;DataSourceTransactionManager&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;transactionManager&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt; ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;它通过同一数据源获取的 JDBC &lt;code&gt;Connection&lt;/code&gt; 管理事务，并最终调用连接的 &lt;code&gt;commit()&lt;/code&gt; 或 &lt;code&gt;rollback()&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;JPA 事务&lt;a href=&quot;#jpa-事务&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;使用 JPA 时，通常使用 &lt;code&gt;JpaTransactionManager&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;transactionManager&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.springframework.orm.jpa.JpaTransactionManager&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;entityManagerFactory&quot;&lt;/span&gt;&lt;span&gt; ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;entityManagerFactory&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;JpaTransactionManager&lt;/code&gt; 与 JPA 的 &lt;code&gt;EntityManagerFactory&lt;/code&gt;、&lt;code&gt;EntityManager&lt;/code&gt; 协作管理事务。&lt;/p&gt;
&lt;h3&gt;Hibernate 事务&lt;a href=&quot;#hibernate-事务&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;直接使用原生 Hibernate &lt;code&gt;SessionFactory&lt;/code&gt; 时，可以使用 &lt;code&gt;HibernateTransactionManager&lt;/code&gt;。如果项目通过 JPA 使用 Hibernate 实现，则应优先使用 &lt;code&gt;JpaTransactionManager&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;transactionManager&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.springframework.orm.hibernate5.HibernateTransactionManager&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;sessionFactory&quot;&lt;/span&gt;&lt;span&gt; ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;sessionFactory&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;JTA 事务&lt;a href=&quot;#jta-事务&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;当一个业务操作需要协调多个事务资源时，可以使用 JTA 和 &lt;code&gt;JtaTransactionManager&lt;/code&gt;。例如，一个事务同时涉及多个数据库或数据库与消息系统。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;transactionManager&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.springframework.transaction.jta.JtaTransactionManager&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;JTA 的具体配置依赖应用服务器或所使用的事务协调器，不能仅靠一个固定 Bean 配置适配所有环境。&lt;/p&gt;
&lt;h2&gt;事务属性&lt;a href=&quot;#事务属性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;TransactionDefinition&lt;/code&gt; 用于描述事务策略，主要包含传播行为、隔离级别、超时时间、只读标记和事务名称。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730193619101.png&quot; alt=&quot;image-002&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-002&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; TransactionDefinition&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; getPropagationBehavior&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; getIsolationLevel&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; getTimeout&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    boolean&lt;/span&gt;&lt;span&gt; isReadOnly&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    String &lt;/span&gt;&lt;span&gt;getName&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;事务传播行为&lt;a href=&quot;#事务传播行为&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;传播行为决定一个带事务的方法被其他事务方法调用时，应加入现有事务、创建新事务，还是禁止事务。&lt;/p&gt;





































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;传播行为&lt;/th&gt;&lt;th&gt;含义&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;REQUIRED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;默认值。有事务则加入，没有事务则新建事务。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SUPPORTS&lt;/code&gt;&lt;/td&gt;&lt;td&gt;有事务则加入，没有事务则以非事务方式运行。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;MANDATORY&lt;/code&gt;&lt;/td&gt;&lt;td&gt;必须存在事务，否则抛出异常。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;REQUIRES_NEW&lt;/code&gt;&lt;/td&gt;&lt;td&gt;总是创建新事务；若已有事务，则暂停外层事务。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;NOT_SUPPORTED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;以非事务方式运行；若已有事务，则暂停该事务。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;NEVER&lt;/code&gt;&lt;/td&gt;&lt;td&gt;必须以非事务方式运行；若存在事务，则抛出异常。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;NESTED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;有事务时使用保存点形成嵌套范围；没有事务时行为类似 &lt;code&gt;REQUIRED&lt;/code&gt;。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;&lt;code&gt;REQUIRED&lt;/code&gt;&lt;a href=&quot;#required&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;多个方法加入同一个物理事务，其中任意参与者把事务标记为仅回滚，最终提交时整个事务都会回滚。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;propagation&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Propagation.REQUIRED)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; saveOrder&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 业务逻辑&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;REQUIRES_NEW&lt;/code&gt;&lt;a href=&quot;#requires_new&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;内层方法使用独立事务，外层事务在内层事务执行期间被挂起。内层事务提交后，即使外层事务随后回滚，内层已提交内容通常不会随之回滚。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;propagation&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Propagation.REQUIRES_NEW)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; saveAuditLog&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 独立保存审计日志&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;NESTED&lt;/code&gt;&lt;a href=&quot;#nested&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;NESTED&lt;/code&gt; 通常基于同一个物理事务中的 JDBC 保存点实现。内层范围可以回滚到保存点，但它不能像独立事务一样脱离外层事务单独最终提交；外层事务回滚时，嵌套范围也会回滚。&lt;/p&gt;
&lt;p&gt;该传播行为依赖事务管理器和底层资源对保存点的支持，常见于 JDBC 资源事务。&lt;/p&gt;
&lt;h2&gt;事务隔离级别&lt;a href=&quot;#事务隔离级别&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;隔离级别用于控制并发事务之间的数据可见性。&lt;/p&gt;
&lt;h3&gt;并发事务常见问题&lt;a href=&quot;#并发事务常见问题&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;脏读：读取到其他事务尚未提交的数据。&lt;/li&gt;
&lt;li&gt;不可重复读：同一事务内两次读取同一行，得到不同值，通常由其他事务更新并提交引起。&lt;/li&gt;
&lt;li&gt;幻读：同一事务内按相同条件查询两次，结果集中的行数发生变化，通常由其他事务插入或删除并提交引起。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Spring 隔离级别&lt;a href=&quot;#spring-隔离级别&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;隔离级别&lt;/th&gt;&lt;th&gt;含义&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DEFAULT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;使用数据库默认隔离级别。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;READ_UNCOMMITTED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;允许读取未提交数据，可能出现脏读、不可重复读和幻读。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;READ_COMMITTED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;只能读取已提交数据，可避免脏读。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;REPEATABLE_READ&lt;/code&gt;&lt;/td&gt;&lt;td&gt;同一事务内重复读取已读取行时保持一致，可避免脏读和不可重复读。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SERIALIZABLE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;事务近似串行执行，隔离程度最高，但并发性能通常最低。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;不同数据库的锁机制和多版本并发控制实现不同，因此同名隔离级别在具体细节上可能存在差异。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;isolation&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Isolation.READ_COMMITTED)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; updateAccount&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 业务逻辑&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;只读事务&lt;a href=&quot;#只读事务&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;只读标记表示该事务主要执行查询操作，事务管理器和数据库可以据此进行优化。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;readOnly&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; User &lt;/span&gt;&lt;span&gt;queryById&lt;/span&gt;&lt;span&gt;(Long id) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; userMapper.&lt;/span&gt;&lt;span&gt;selectById&lt;/span&gt;&lt;span&gt;(id);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;readOnly = true&lt;/code&gt; 通常是一种优化提示，不应把它当作绝对的数据库写入安全限制。是否真正禁止写操作取决于事务管理器和数据库实现。&lt;/p&gt;
&lt;h2&gt;事务超时&lt;a href=&quot;#事务超时&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;事务超时用于限制事务允许执行的最长时间。超时后，事务通常会被标记为回滚。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;timeout&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; 10&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; importData&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 业务逻辑&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;应避免在事务中执行长时间网络调用、文件处理或人为等待，否则会长期占用数据库连接和锁资源。&lt;/p&gt;
&lt;h2&gt;回滚规则&lt;a href=&quot;#回滚规则&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Spring 声明式事务默认在抛出 &lt;code&gt;RuntimeException&lt;/code&gt; 或 &lt;code&gt;Error&lt;/code&gt; 时回滚；对于普通受检异常，默认不回滚。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;rollbackFor&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Exception.class)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; transfer&lt;/span&gt;&lt;span&gt;() throws Exception {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 发生受检异常时也回滚&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也可以通过 &lt;code&gt;noRollbackFor&lt;/code&gt; 指定某些异常不触发回滚。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;noRollbackFor&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; BusinessWarningException.class)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; execute&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 业务逻辑&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;回滚规则应根据业务语义设置，不建议无差别捕获异常后静默处理。若异常被方法内部捕获且不再抛出，事务拦截器通常无法感知该异常，也就不会按异常自动回滚。&lt;/p&gt;
&lt;h2&gt;事务状态&lt;a href=&quot;#事务状态&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;TransactionStatus&lt;/code&gt; 表示当前事务的运行状态，并提供保存点和仅回滚标记等能力。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; TransactionStatus&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; TransactionExecution&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;SavepointManager&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Flushable&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    boolean&lt;/span&gt;&lt;span&gt; hasSavepoint&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    void&lt;/span&gt;&lt;span&gt; flush&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常见状态方法包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;isNewTransaction()&lt;/code&gt;：是否为当前调用新建了事务。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hasSavepoint()&lt;/code&gt;：是否持有保存点。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;setRollbackOnly()&lt;/code&gt;：把事务标记为只能回滚。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isRollbackOnly()&lt;/code&gt;：事务是否已被标记为回滚。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isCompleted()&lt;/code&gt;：事务是否已经完成。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;接口的具体方法会随 Spring 版本演进，使用时应以当前项目依赖中的 API 为准。&lt;/p&gt;
&lt;h2&gt;编程式事务&lt;a href=&quot;#编程式事务&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;编程式事务由业务代码明确控制事务边界，适合事务范围需要动态决定或精细控制的场景。它的缺点是事务代码会进入业务逻辑，侵入性较强。&lt;/p&gt;
&lt;h3&gt;使用 &lt;code&gt;TransactionTemplate&lt;/code&gt;&lt;a href=&quot;#使用-transactiontemplate&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;TransactionTemplate&lt;/code&gt; 是推荐的编程式事务方式之一。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; UserService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; TransactionTemplate transactionTemplate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; UserRepository userRepository;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; UserService&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            TransactionTemplate &lt;/span&gt;&lt;span&gt;transactionTemplate&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            UserRepository &lt;/span&gt;&lt;span&gt;userRepository&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.transactionTemplate &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; transactionTemplate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.userRepository &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; userRepository;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Boolean &lt;/span&gt;&lt;span&gt;save&lt;/span&gt;&lt;span&gt;(User &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; transactionTemplate.&lt;/span&gt;&lt;span&gt;execute&lt;/span&gt;&lt;span&gt;(status &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                userRepository.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(user);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (RuntimeException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                status.&lt;/span&gt;&lt;span&gt;setRollbackOnly&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                throw&lt;/span&gt;&lt;span&gt; e;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        });&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;如果回调抛出运行时异常，事务模板会按规则回滚。只有在需要把异常转换为正常返回值时，才需要显式调用 &lt;code&gt;setRollbackOnly()&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;直接使用 &lt;code&gt;PlatformTransactionManager&lt;/code&gt;&lt;a href=&quot;#直接使用-platformtransactionmanager&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;DefaultTransactionDefinition definition &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; DefaultTransactionDefinition&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;definition.&lt;/span&gt;&lt;span&gt;setPropagationBehavior&lt;/span&gt;&lt;span&gt;(TransactionDefinition.PROPAGATION_REQUIRED);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;TransactionStatus status &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; transactionManager.&lt;/span&gt;&lt;span&gt;getTransaction&lt;/span&gt;&lt;span&gt;(definition);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    userRepository.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(user);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    transactionManager.&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt;(status);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (RuntimeException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    transactionManager.&lt;/span&gt;&lt;span&gt;rollback&lt;/span&gt;&lt;span&gt;(status);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    throw&lt;/span&gt;&lt;span&gt; e;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;直接操作事务管理器更灵活，但需要自己保证提交、回滚和异常传播逻辑正确。&lt;/p&gt;
&lt;h2&gt;声明式事务&lt;a href=&quot;#声明式事务&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;声明式事务基于 Spring AOP，通过配置或注解把事务逻辑应用到目标方法，业务代码不需要手动提交和回滚。&lt;/p&gt;
&lt;h3&gt;XML 配置方式&lt;a href=&quot;#xml-配置方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;transactionManager&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt; ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;tx:advice&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;txAdvice&quot;&lt;/span&gt;&lt;span&gt; transaction-manager&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;transactionManager&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;tx:attributes&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;tx:method&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;query*&quot;&lt;/span&gt;&lt;span&gt; read-only&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;tx:method&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;get*&quot;&lt;/span&gt;&lt;span&gt; read-only&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;tx:method&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;*&quot;&lt;/span&gt;&lt;span&gt; propagation&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;REQUIRED&quot;&lt;/span&gt;&lt;span&gt; rollback-for&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;java.lang.Exception&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;tx:attributes&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;tx:advice&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;aop:config&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;aop:pointcut&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;servicePointcut&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                  expression&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;execution(* com.example.service..*(..))&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;aop:advisor&lt;/span&gt;&lt;span&gt; advice-ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;txAdvice&quot;&lt;/span&gt;&lt;span&gt; pointcut-ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;servicePointcut&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;aop:config&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;需要在根元素中声明 &lt;code&gt;tx&lt;/code&gt; 和 &lt;code&gt;aop&lt;/code&gt; 命名空间。&lt;/p&gt;
&lt;h3&gt;注解方式&lt;a href=&quot;#注解方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;先启用事务注解：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;tx:annotation-driven&lt;/span&gt;&lt;span&gt; transaction-manager&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;transactionManager&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也可以使用 Java 配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;EnableTransactionManagement&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; TransactionConfig&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; PlatformTransactionManager &lt;/span&gt;&lt;span&gt;transactionManager&lt;/span&gt;&lt;span&gt;(DataSource &lt;/span&gt;&lt;span&gt;dataSource&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; DataSourceTransactionManager&lt;/span&gt;&lt;span&gt;(dataSource);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在业务类或方法上使用 &lt;code&gt;@Transactional&lt;/code&gt;：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; UserService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; UserDao userDao;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; UserService&lt;/span&gt;&lt;span&gt;(UserDao &lt;/span&gt;&lt;span&gt;userDao&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.userDao &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; userDao;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;rollbackFor&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Exception.class)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; save&lt;/span&gt;&lt;span&gt;(User &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Exception {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        userDao.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(user);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;类上的注解会作为该类方法的默认事务配置；方法上的注解可以覆盖类级配置。&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;@Transactional&lt;/code&gt; 常见失效场景&lt;a href=&quot;#transactional-常见失效场景&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;同类内部调用&lt;a href=&quot;#同类内部调用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;默认代理模式下，一个方法通过 &lt;code&gt;this&lt;/code&gt; 调用同类中的另一个 &lt;code&gt;@Transactional&lt;/code&gt; 方法时，调用没有经过 Spring 代理，内层方法的独立事务配置通常不会生效。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; OrderService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; createOrder&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 这是同类内部调用，不会经过代理对象。&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        saveOrder&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; saveOrder&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 数据库操作&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;通常应把需要独立事务边界的方法拆分到另一个 Spring Bean 中。&lt;/p&gt;
&lt;h3&gt;方法不可代理&lt;a href=&quot;#方法不可代理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在常见代理模式下，事务通常应应用于可被代理调用的公开实例方法。&lt;code&gt;private&lt;/code&gt; 方法、静态方法和对象自行创建的方法不会按普通 Spring Bean 代理方式生效。&lt;/p&gt;
&lt;h3&gt;对象不是 Spring Bean&lt;a href=&quot;#对象不是-spring-bean&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;通过 &lt;code&gt;new&lt;/code&gt; 手动创建的对象不受 Spring 容器管理，其 &lt;code&gt;@Transactional&lt;/code&gt; 注解不会自动生效。&lt;/p&gt;
&lt;h3&gt;异常被捕获&lt;a href=&quot;#异常被捕获&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; save&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        userDao.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (Exception &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 异常被吞掉后，事务拦截器无法按该异常自动回滚。&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;应重新抛出异常，或根据业务需要调用 &lt;code&gt;TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;异常类型不匹配&lt;a href=&quot;#异常类型不匹配&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;受检异常默认不会触发回滚。需要回滚时，应通过 &lt;code&gt;rollbackFor&lt;/code&gt; 明确配置。&lt;/p&gt;
&lt;h2&gt;使用建议&lt;a href=&quot;#使用建议&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;事务通常放在 Service 层，而不是 Controller 层。&lt;/li&gt;
&lt;li&gt;一个事务只覆盖必须保持一致性的数据库操作。&lt;/li&gt;
&lt;li&gt;避免在事务中进行长时间远程调用。&lt;/li&gt;
&lt;li&gt;查询方法可设置为只读事务。&lt;/li&gt;
&lt;li&gt;根据业务语义选择传播行为，不要把所有方法都配置成 &lt;code&gt;REQUIRES_NEW&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;对异常进行转换时，应保留原始异常信息，并确保回滚规则仍然生效。&lt;/li&gt;
&lt;/ul&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:框架</category><category>tag:Spring</category></item><item><title>Spring MVC</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/framework/spring-mvc</link><guid isPermaLink="false">learn/hyxy/framework/spring-mvc</guid><description>Spring MVC
image-001
核心执行流程
Spring MVC 处理请求时，主要组件及职责如下：

DispatcherServlet：前端控制器，统一接收请求并协调后续处理流程。
HandlerMapping：根据请求地址查找对应的处理器方法。</description><pubDate>Thu, 30 Jul 2026 11:35:54 GMT</pubDate><content:encoded>&lt;h1&gt;Spring MVC&lt;a href=&quot;#spring-mvc&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730193509346.png&quot; alt=&quot;image-001&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-001&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;核心执行流程&lt;a href=&quot;#核心执行流程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Spring MVC 处理请求时，主要组件及职责如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DispatcherServlet&lt;/code&gt;：前端控制器，统一接收请求并协调后续处理流程。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;HandlerMapping&lt;/code&gt;：根据请求地址查找对应的处理器方法。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;HandlerAdapter&lt;/code&gt;：以统一方式调用处理器，并完成参数解析等工作。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Handler&lt;/code&gt;：实际处理请求的控制器方法。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ModelAndView&lt;/code&gt;：同时封装模型数据和逻辑视图名。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ViewResolver&lt;/code&gt;：把逻辑视图名解析为具体视图。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;View&lt;/code&gt;：负责渲染响应内容。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;搭建传统 Spring MVC 项目&lt;a href=&quot;#搭建传统-spring-mvc-项目&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;创建 Maven Web 工程&lt;a href=&quot;#创建-maven-web-工程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;引入 Spring MVC 依赖。以下版本仅对应原课程示例环境：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-webmvc&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;5.2.4.RELEASE&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;配置 &lt;code&gt;DispatcherServlet&lt;/code&gt;&lt;a href=&quot;#配置-dispatcherservlet&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 &lt;code&gt;web.xml&lt;/code&gt; 中注册前端控制器：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;servlet&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;servlet-name&lt;/span&gt;&lt;span&gt;&amp;gt;spring&amp;lt;/&lt;/span&gt;&lt;span&gt;servlet-name&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;servlet-class&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.web.servlet.DispatcherServlet&amp;lt;/&lt;/span&gt;&lt;span&gt;servlet-class&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;init-param&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;param-name&lt;/span&gt;&lt;span&gt;&amp;gt;contextConfigLocation&amp;lt;/&lt;/span&gt;&lt;span&gt;param-name&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;param-value&lt;/span&gt;&lt;span&gt;&amp;gt;classpath:spring-servlet.xml&amp;lt;/&lt;/span&gt;&lt;span&gt;param-value&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;init-param&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;load-on-startup&lt;/span&gt;&lt;span&gt;&amp;gt;1&amp;lt;/&lt;/span&gt;&lt;span&gt;load-on-startup&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;servlet&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;servlet-mapping&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;servlet-name&lt;/span&gt;&lt;span&gt;&amp;gt;spring&amp;lt;/&lt;/span&gt;&lt;span&gt;servlet-name&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;url-pattern&lt;/span&gt;&lt;span&gt;&amp;gt;/&amp;lt;/&lt;/span&gt;&lt;span&gt;url-pattern&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;servlet-mapping&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;/&lt;/code&gt; 表示让 &lt;code&gt;DispatcherServlet&lt;/code&gt; 处理除容器内部特殊请求之外的大部分请求，同时仍可由默认 Servlet 处理静态资源。通常不建议配置为 &lt;code&gt;/*&lt;/code&gt;，因为它可能影响 JSP 转发等容器行为。&lt;/p&gt;
&lt;h3&gt;创建 Spring MVC 配置文件&lt;a href=&quot;#创建-spring-mvc-配置文件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;beans&lt;/span&gt;&lt;span&gt; xmlns&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://www.springframework.org/schema/beans&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       xmlns:xsi&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       xmlns:context&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://www.springframework.org/schema/context&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       xmlns:mvc&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://www.springframework.org/schema/mvc&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       xsi:schemaLocation&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           http://www.springframework.org/schema/beans&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           https://www.springframework.org/schema/beans/spring-beans.xsd&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           http://www.springframework.org/schema/context&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           https://www.springframework.org/schema/context/spring-context.xsd&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           http://www.springframework.org/schema/mvc&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           https://www.springframework.org/schema/mvc/spring-mvc.xsd&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;context:component-scan&lt;/span&gt;&lt;span&gt; base-package&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.controller&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;mvc:annotation-driven&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;beans&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;创建控制器&lt;a href=&quot;#创建控制器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Controller&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; TestController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;RequestMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/test&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;ResponseBody&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;test&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; &quot;test&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动服务器后访问 &lt;code&gt;/test&lt;/code&gt;，响应体中会返回 &lt;code&gt;test&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;请求映射&lt;a href=&quot;#请求映射&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;@RequestMapping&lt;/code&gt;&lt;a href=&quot;#requestmapping&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;@RequestMapping&lt;/code&gt; 可以修饰类和方法。修饰类时通常表示统一的地址前缀；修饰方法时表示具体请求映射。&lt;/p&gt;
&lt;p&gt;常用属性包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;value&lt;/code&gt; 或 &lt;code&gt;path&lt;/code&gt;：请求地址。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;method&lt;/code&gt;：允许的请求方法。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;params&lt;/code&gt;：要求请求中包含或不包含指定参数。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;headers&lt;/code&gt;：根据请求头进一步限制映射。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;consumes&lt;/code&gt;：限制请求体的媒体类型。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;produces&lt;/code&gt;：声明响应媒体类型。&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Controller&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequestMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/test&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; TestController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;RequestMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;/add&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; RequestMethod.POST)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;ResponseBody&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; &quot;add&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;在实际项目中，也可使用语义更明确的组合注解，例如 &lt;code&gt;@GetMapping&lt;/code&gt;、&lt;code&gt;@PostMapping&lt;/code&gt;、&lt;code&gt;@PutMapping&lt;/code&gt; 和 &lt;code&gt;@DeleteMapping&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;请求参数绑定&lt;a href=&quot;#请求参数绑定&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;绑定简单参数&lt;a href=&quot;#绑定简单参数&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;请求参数名与方法参数名一致时，Spring MVC 可以自动绑定。若编译时未保留参数名，或希望显式指定参数名称，应使用 &lt;code&gt;@RequestParam&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/user&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;ResponseBody&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;getUser&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        @&lt;/span&gt;&lt;span&gt;RequestParam&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;name&quot;&lt;/span&gt;&lt;span&gt;) String username,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        @&lt;/span&gt;&lt;span&gt;RequestParam&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;age&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;required&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;defaultValue&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;0&quot;&lt;/span&gt;&lt;span&gt;) Integer age) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; username &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;:&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; age;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用基本类型接收可选参数时，参数缺失会导致类型转换失败，因此可选数字参数一般使用包装类型。&lt;/p&gt;
&lt;h3&gt;绑定路径变量&lt;a href=&quot;#绑定路径变量&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/add/{name}/{pwd}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;ResponseBody&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        @&lt;/span&gt;&lt;span&gt;PathVariable&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;) String username,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        @&lt;/span&gt;&lt;span&gt;PathVariable&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;pwd&quot;&lt;/span&gt;&lt;span&gt;) String password) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; username &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;:&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; password;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;例如访问 &lt;code&gt;http://localhost:8088/mvc/test/add/tom/123&lt;/code&gt;，&lt;code&gt;username&lt;/code&gt; 的值为 &lt;code&gt;tom&lt;/code&gt;，&lt;code&gt;password&lt;/code&gt; 的值为 &lt;code&gt;123&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;读取请求头和 Cookie&lt;a href=&quot;#读取请求头和-cookie&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/header&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;ResponseBody&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;header&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        @&lt;/span&gt;&lt;span&gt;RequestHeader&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Accept&quot;&lt;/span&gt;&lt;span&gt;) String accept,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        @&lt;/span&gt;&lt;span&gt;CookieValue&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;username&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;defaultValue&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;rose&quot;&lt;/span&gt;&lt;span&gt;) String username) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; accept &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;:&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; username;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;绑定 Java 对象&lt;a href=&quot;#绑定-java-对象&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;请求参数名与对象属性名一致时，可以把参数绑定到对象中。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;PostMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/emp&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;ResponseBody&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; Emp &lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(Emp emp) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; emp;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;对于关联对象，可使用属性路径传参。例如 &lt;code&gt;Emp&lt;/code&gt; 中包含 &lt;code&gt;Dept dept&lt;/code&gt; 时，请求参数可写成 &lt;code&gt;dept.deptName=开发部&lt;/code&gt;。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String empNo;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Dept dept;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // getter 和 setter&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Dept&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String deptName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // getter 和 setter&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;获取 Servlet API 对象&lt;a href=&quot;#获取-servlet-api-对象&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;需要访问原始请求或会话时，可直接在控制器方法参数中声明。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/request-info&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;ResponseBody&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;requestInfo&lt;/span&gt;&lt;span&gt;(HttpServletRequest request, HttpSession session) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    session.&lt;/span&gt;&lt;span&gt;setAttribute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;method&quot;&lt;/span&gt;&lt;span&gt;, request.&lt;/span&gt;&lt;span&gt;getMethod&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; request.&lt;/span&gt;&lt;span&gt;getMethod&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;业务代码不应过度依赖 Servlet API。能通过注解和参数绑定完成的场景，应优先使用 Spring MVC 的参数解析机制。&lt;/p&gt;
&lt;h2&gt;视图跳转与模型数据&lt;a href=&quot;#视图跳转与模型数据&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;返回逻辑视图名&lt;a href=&quot;#返回逻辑视图名&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/books&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;books&lt;/span&gt;&lt;span&gt;(Model model) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    model.&lt;/span&gt;&lt;span&gt;addAttribute&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;bookList&quot;&lt;/span&gt;&lt;span&gt;, List.&lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Java&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;Spring&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; &quot;book/list&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;配合视图解析器时，&lt;code&gt;book/list&lt;/code&gt; 会被解析为具体页面路径。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.springframework.web.servlet.view.InternalResourceViewResolver&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;prefix&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;/WEB-INF/views/&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;suffix&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;.jsp&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;返回 &lt;code&gt;ModelAndView&lt;/code&gt;&lt;a href=&quot;#返回-modelandview&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/detail&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; ModelAndView &lt;/span&gt;&lt;span&gt;detail&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ModelAndView modelAndView &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; ModelAndView&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    modelAndView.&lt;/span&gt;&lt;span&gt;addObject&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;Spring MVC&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    modelAndView.&lt;/span&gt;&lt;span&gt;setViewName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;book/detail&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; modelAndView;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;静态资源处理&lt;a href=&quot;#静态资源处理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;可以显式配置静态资源映射：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;mvc:annotation-driven&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;mvc:resources&lt;/span&gt;&lt;span&gt; mapping&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;/html/**&quot;&lt;/span&gt;&lt;span&gt; location&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;/html/&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也可使用默认 Servlet 处理未匹配的静态资源：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;mvc:default-servlet-handler&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;前后端分离开发&lt;a href=&quot;#前后端分离开发&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;@RequestBody&lt;/code&gt;&lt;a href=&quot;#requestbody&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;@RequestBody&lt;/code&gt; 会读取请求体，并通过消息转换器把 JSON 转换为 Java 对象。请求头通常应包含 &lt;code&gt;Content-Type: application/json&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.fasterxml.jackson.core&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;jackson-databind&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;2.14.2&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequestMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/test&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; TestController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PostMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/emp&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Emp &lt;/span&gt;&lt;span&gt;save&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;RequestBody&lt;/span&gt;&lt;span&gt; Emp &lt;/span&gt;&lt;span&gt;emp&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; emp;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730193515003.png&quot; alt=&quot;image-002&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-002&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;JSON 字段名应与 Java 属性名匹配。字段命名不一致时，可以使用 Jackson 注解进行映射。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;@ResponseBody&lt;/code&gt;&lt;a href=&quot;#responsebody&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;@ResponseBody&lt;/code&gt; 表示把方法返回值写入响应体。返回对象时，Spring MVC 会通过消息转换器将其序列化为 JSON；返回字符串时，通常直接写入文本内容。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/get&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;ResponseBody&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; User &lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    User user &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; User&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    user.&lt;/span&gt;&lt;span&gt;setUsername&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;jack&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    user.&lt;/span&gt;&lt;span&gt;setPassword&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;123456&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; user;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;@RestController&lt;/code&gt;&lt;a href=&quot;#restcontroller&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;@RestController&lt;/code&gt; 相当于类级别的 &lt;code&gt;@Controller&lt;/code&gt; 与 &lt;code&gt;@ResponseBody&lt;/code&gt; 组合，适合以 JSON 为主要响应内容的控制器。&lt;/p&gt;
&lt;h3&gt;统一响应对象&lt;a href=&quot;#统一响应对象&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Result&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; success;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; T data;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String message;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; Result&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;success&lt;/span&gt;&lt;span&gt;(T &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Result&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Result&amp;lt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        result.success &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        result.data &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; data;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; Result&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;failure&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;message&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Result&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Result&amp;lt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        result.success &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        result.message &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; message;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // getter 和 setter&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;跨域请求&lt;a href=&quot;#跨域请求&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;浏览器的同源策略会限制脚本访问不同源的资源。源由协议、主机和端口共同确定，任意一项不同都属于跨源请求。&lt;/p&gt;
&lt;h3&gt;使用 &lt;code&gt;@CrossOrigin&lt;/code&gt;&lt;a href=&quot;#使用-crossorigin&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequestMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/book&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;CrossOrigin&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;origins&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;http://localhost:8081&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; BookController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;全局配置 CORS&lt;a href=&quot;#全局配置-cors&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; WebConfig&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; WebMvcConfigurer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; addCorsMappings&lt;/span&gt;&lt;span&gt;(CorsRegistry &lt;/span&gt;&lt;span&gt;registry&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        registry.&lt;/span&gt;&lt;span&gt;addMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/**&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;allowedOrigins&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;http://localhost:8081&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;allowedMethods&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;GET&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;POST&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;PUT&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;DELETE&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;allowedHeaders&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;*&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;allowCredentials&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;maxAge&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;3600&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;开启凭据时，不能把允许来源简单配置为通配符。生产环境应只开放实际需要的来源、方法和请求头。&lt;/p&gt;
&lt;h3&gt;前端代理与 Nginx 反向代理&lt;a href=&quot;#前端代理与-nginx-反向代理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;开发环境可以通过前端开发服务器代理接口请求；生产环境通常使用 Nginx 将前端静态资源和后端接口统一到同一站点下。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730193518536.png&quot; alt=&quot;image-003&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-003&lt;/figcaption&gt;&lt;/figure&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730193520251.png&quot; alt=&quot;image-004&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-004&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;反向代理只改变请求转发方式，不会替代后端自身的鉴权、权限校验和输入校验。&lt;/p&gt;
&lt;h2&gt;文件上传&lt;a href=&quot;#文件上传&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;配置文件解析器&lt;a href=&quot;#配置文件解析器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在传统 Spring MVC 项目中，可配置 &lt;code&gt;CommonsMultipartResolver&lt;/code&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;multipartResolver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.springframework.web.multipart.commons.CommonsMultipartResolver&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;maxUploadSize&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;5242880&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;defaultEncoding&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;commons-fileupload&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;commons-fileupload&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.4&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;表单应使用 &lt;code&gt;POST&lt;/code&gt; 请求，并设置 &lt;code&gt;enctype=&quot;multipart/form-data&quot;&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;编写上传接口&lt;a href=&quot;#编写上传接口&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; FileUploadController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; Path UPLOAD_DIR &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Paths.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;D:/Lesson/uploadFile&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PostMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/upload&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Result&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;upload&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;RequestParam&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;file&quot;&lt;/span&gt;&lt;span&gt;) MultipartFile &lt;/span&gt;&lt;span&gt;file&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (file.&lt;/span&gt;&lt;span&gt;isEmpty&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            return&lt;/span&gt;&lt;span&gt; Result.&lt;/span&gt;&lt;span&gt;failure&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;上传文件不能为空&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String originalName &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; file.&lt;/span&gt;&lt;span&gt;getOriginalFilename&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String safeName &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; originalName &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                ?&lt;/span&gt;&lt;span&gt; UUID.&lt;/span&gt;&lt;span&gt;randomUUID&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;toString&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                :&lt;/span&gt;&lt;span&gt; Paths.&lt;/span&gt;&lt;span&gt;get&lt;/span&gt;&lt;span&gt;(originalName).&lt;/span&gt;&lt;span&gt;getFileName&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;toString&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Files.&lt;/span&gt;&lt;span&gt;createDirectories&lt;/span&gt;&lt;span&gt;(UPLOAD_DIR);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Path target &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; UPLOAD_DIR.&lt;/span&gt;&lt;span&gt;resolve&lt;/span&gt;&lt;span&gt;(safeName).&lt;/span&gt;&lt;span&gt;normalize&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;target.&lt;/span&gt;&lt;span&gt;startsWith&lt;/span&gt;&lt;span&gt;(UPLOAD_DIR)) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                return&lt;/span&gt;&lt;span&gt; Result.&lt;/span&gt;&lt;span&gt;failure&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;文件名不合法&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            file.&lt;/span&gt;&lt;span&gt;transferTo&lt;/span&gt;&lt;span&gt;(target);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            return&lt;/span&gt;&lt;span&gt; Result.&lt;/span&gt;&lt;span&gt;success&lt;/span&gt;&lt;span&gt;(safeName);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (IOException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            return&lt;/span&gt;&lt;span&gt; Result.&lt;/span&gt;&lt;span&gt;failure&lt;/span&gt;&lt;span&gt;(e.&lt;/span&gt;&lt;span&gt;getMessage&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;不要直接信任客户端提交的原始文件名。实际项目还应检查文件大小、扩展名、MIME 类型和存储权限，并避免把上传目录暴露为可执行目录。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730193522903.png&quot; alt=&quot;image-005&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-005&lt;/figcaption&gt;&lt;/figure&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:框架</category><category>tag:Spring MVC</category></item><item><title>Spring Boot</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/framework/spring-boot</link><guid isPermaLink="false">learn/hyxy/framework/spring-boot</guid><description>Spring Boot
image-001
第一个 Spring Boot 应用
目标是在浏览器访问指定地址时，由服务器返回 Hello World。
创建项目并引入依赖
可以通过 Spring Initializr 创建项目。以下示例使用 Spring Boot 3.3.4，因此运行环境至少需要</description><pubDate>Thu, 30 Jul 2026 11:34:35 GMT</pubDate><content:encoded>&lt;h1&gt;Spring Boot&lt;a href=&quot;#spring-boot&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730193336260.png&quot; alt=&quot;image-001&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-001&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h2&gt;第一个 Spring Boot 应用&lt;a href=&quot;#第一个-spring-boot-应用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;目标是在浏览器访问指定地址时，由服务器返回 &lt;code&gt;Hello World&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;创建项目并引入依赖&lt;a href=&quot;#创建项目并引入依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;可以通过 Spring Initializr 创建项目。以下示例使用 Spring Boot &lt;code&gt;3.3.4&lt;/code&gt;，因此运行环境至少需要 Java &lt;code&gt;17&lt;/code&gt;。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;parent&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-parent&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.3.4&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;relativePath&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;parent&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-web&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-test&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;test&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;编写控制器&lt;a href=&quot;#编写控制器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; HelloController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/test&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;test&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; &quot;Hello World&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;启动项目后访问 &lt;code&gt;http://localhost:8080/test&lt;/code&gt;，浏览器将显示 &lt;code&gt;Hello World&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;打包与部署&lt;a href=&quot;#打包与部署&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;配置 Maven 插件&lt;a href=&quot;#配置-maven-插件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-maven-plugin&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;生成可执行 JAR&lt;a href=&quot;#生成可执行-jar&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在项目根目录执行：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;mvn&lt;/span&gt;&lt;span&gt; clean&lt;/span&gt;&lt;span&gt; package&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;构建成功后，可在 &lt;code&gt;target&lt;/code&gt; 目录找到 JAR 文件。&lt;/p&gt;
&lt;h3&gt;运行项目&lt;a href=&quot;#运行项目&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;java&lt;/span&gt;&lt;span&gt; -jar&lt;/span&gt;&lt;span&gt; target/项目名称.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Spring Boot 的核心机制&lt;a href=&quot;#spring-boot-的核心机制&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;父工程与依赖管理&lt;a href=&quot;#父工程与依赖管理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730193344277.png&quot; alt=&quot;image-002&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-002&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;spring-boot-starter-parent&lt;/code&gt; 提供常用 Maven 配置，并继承 Spring Boot 的依赖管理能力。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730193346042.png&quot; alt=&quot;image-003&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-003&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Spring Boot 会统一管理大量常用依赖的版本。引入已被管理的依赖时，通常不需要单独声明版本，从而降低版本冲突的概率。&lt;/p&gt;
&lt;h3&gt;Starter 场景启动器&lt;a href=&quot;#starter-场景启动器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;spring-boot-starter-web&lt;/code&gt; 是 Web 场景启动器，会引入 Spring MVC、JSON 处理和默认嵌入式服务器等相关依赖。&lt;/p&gt;
&lt;p&gt;如果需要把默认的 Tomcat 替换为 Jetty，可以排除 Tomcat 并引入 Jetty：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-web&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;exclusions&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;exclusion&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-tomcat&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;exclusion&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;exclusions&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-jetty&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;启动类与 &lt;code&gt;SpringApplication.run()&lt;/code&gt;&lt;a href=&quot;#启动类与-springapplicationrun&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;SpringBootApplication&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; SpringBootDemoApplication&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        ConfigurableApplicationContext applicationContext &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                SpringApplication.&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;(SpringBootDemoApplication.class, args);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(applicationContext.&lt;/span&gt;&lt;span&gt;getBean&lt;/span&gt;&lt;span&gt;(HelloController.class));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;SpringApplication.run()&lt;/code&gt; 会启动 Spring 容器，执行自动配置，并在 Web 项目中启动嵌入式服务器。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;@SpringBootApplication&lt;/code&gt;&lt;a href=&quot;#springbootapplication&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;@SpringBootApplication&lt;/code&gt; 是组合注解，主要包含以下能力：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@SpringBootConfiguration&lt;/code&gt;：表明当前类是 Spring Boot 配置类，本质上具有 &lt;code&gt;@Configuration&lt;/code&gt; 的作用。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@EnableAutoConfiguration&lt;/code&gt;：根据类路径中的依赖、已有 Bean 和配置属性进行自动配置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@ComponentScan&lt;/code&gt;：默认扫描启动类所在包及其子包。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此，控制器、业务类、配置类等通常应放在启动类所在包或其子包中。若包结构不满足默认扫描范围，需要显式配置扫描路径。&lt;/p&gt;
&lt;h3&gt;自动配置&lt;a href=&quot;#自动配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;自动配置并不是无条件注册所有 Bean。Spring Boot 会结合依赖、配置属性和容器中已有 Bean 判断某项配置是否生效。&lt;/p&gt;
&lt;p&gt;例如，引入 Web Starter 后，Spring Boot 会为 Spring MVC 应用配置 &lt;code&gt;DispatcherServlet&lt;/code&gt;、请求映射、消息转换器等组件。开发者自己声明同类型 Bean 时，部分自动配置会按条件退让。&lt;/p&gt;
&lt;h2&gt;配置文件&lt;a href=&quot;#配置文件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Spring Boot 默认支持 &lt;code&gt;application.properties&lt;/code&gt; 和 &lt;code&gt;application.yml&lt;/code&gt;。YAML 通过缩进表示层级，缩进必须使用空格，不能使用制表符。&lt;/p&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730193349408.png&quot; alt=&quot;image-004&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-004&lt;/figcaption&gt;&lt;/figure&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;person&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  last-name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;tom&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  age&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  married&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  birth&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1995-03-23&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  maps&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    name1&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;jack&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    name2&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;rose&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  friends&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - &lt;/span&gt;&lt;span&gt;zhangsan&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    - &lt;/span&gt;&lt;span&gt;lisi&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  dog&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;dog&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    age&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;使用 &lt;code&gt;@ConfigurationProperties&lt;/code&gt;&lt;a href=&quot;#使用-configurationproperties&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;ConfigurationProperties&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;prefix&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;person&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Person&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String lastName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer age;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Boolean married;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDate birth;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; maps;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; friends;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Dog dog;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // getter 和 setter&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;@ConfigurationProperties&lt;/code&gt; 适合批量绑定同一前缀下的配置。属性名支持宽松绑定，例如配置中的 &lt;code&gt;last-name&lt;/code&gt; 可以绑定到 Java 属性 &lt;code&gt;lastName&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;对于配置类，也可以配合 &lt;code&gt;@ConfigurationPropertiesScan&lt;/code&gt; 或 &lt;code&gt;@EnableConfigurationProperties&lt;/code&gt; 注册，而不必在配置对象上添加 &lt;code&gt;@Component&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;@Value&lt;/code&gt;、&lt;code&gt;@PropertySource&lt;/code&gt; 与 &lt;code&gt;@ImportResource&lt;/code&gt;&lt;a href=&quot;#valuepropertysource-与-importresource&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@Value&lt;/code&gt; 适合读取少量独立配置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@PropertySource&lt;/code&gt; 可加载额外的 &lt;code&gt;.properties&lt;/code&gt; 文件，但不直接支持 YAML。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@ImportResource&lt;/code&gt; 可导入传统 Spring XML 配置。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;多环境配置&lt;a href=&quot;#多环境配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Spring Boot 使用 Profile 管理不同环境的配置。&lt;/p&gt;
&lt;h3&gt;多文件方式&lt;a href=&quot;#多文件方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;application.yml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;application-dev.yml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;application-test.yml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;application-prod.yml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在主配置中激活环境：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;spring&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  profiles&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    active&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;dev&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也可以通过启动参数覆盖：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;java&lt;/span&gt;&lt;span&gt; -jar&lt;/span&gt;&lt;span&gt; app.jar&lt;/span&gt;&lt;span&gt; --spring.profiles.active=prod&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;单文件多文档方式&lt;a href=&quot;#单文件多文档方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;figure&gt;&lt;img src=&quot;https://r2.hoshiumi.xyz/old_img/20260730193415605.png&quot; alt=&quot;image-005&quot; loading=&quot;lazy&quot; /&gt;&lt;figcaption&gt;image-005&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;YAML 可以使用 &lt;code&gt;---&lt;/code&gt; 分隔多个文档，并通过 &lt;code&gt;spring.config.activate.on-profile&lt;/code&gt; 指定对应环境。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;spring&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  application&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;demo&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;spring&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  config&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    activate&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      on-profile&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;dev&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  port&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;8080&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;spring&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  config&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    activate&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      on-profile&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;prod&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;server&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  port&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;80&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;开发工具与热部署&lt;a href=&quot;#开发工具与热部署&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;引入 DevTools 后，类路径发生变化时可以触发应用重启。它属于开发辅助工具，不应作为生产环境部署方案。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-devtools&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;runtime&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;gt;true&amp;lt;/&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;IDE 还需要开启自动编译或手动触发构建，否则修改后的类文件没有更新，DevTools 也不会重启应用。&lt;/p&gt;
&lt;h2&gt;Lombok 简化实体类&lt;a href=&quot;#lombok-简化实体类&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;NoArgsConstructor&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;AllArgsConstructor&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Accessors&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;chain&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;ConfigurationProperties&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;prefix&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;person&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Person&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String lastName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer age;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Boolean married;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDate birth;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; maps;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; friends;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Dog dog;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Lombok 会在编译阶段生成常用方法。使用时应安装 IDE 插件并开启注解处理，避免编辑器误报。&lt;/p&gt;
&lt;h2&gt;配置 Spring MVC 拦截器&lt;a href=&quot;#配置-spring-mvc-拦截器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;编写拦截器&lt;a href=&quot;#编写拦截器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Spring Boot 3 使用 &lt;code&gt;jakarta.servlet&lt;/code&gt; 包下的 Servlet API。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MyInterceptor&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; HandlerInterceptor&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; preHandle&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            HttpServletRequest &lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            HttpServletResponse &lt;/span&gt;&lt;span&gt;response&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Object &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;preHandle&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; postHandle&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            HttpServletRequest &lt;/span&gt;&lt;span&gt;request&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            HttpServletResponse &lt;/span&gt;&lt;span&gt;response&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Object &lt;/span&gt;&lt;span&gt;handler&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            ModelAndView &lt;/span&gt;&lt;span&gt;modelAndView&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;postHandle&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;注册拦截器&lt;a href=&quot;#注册拦截器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;推荐把拦截器本身注册为 Bean，再通过构造器注入到配置类中。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MyMvcConfig&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; WebMvcConfigurer&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; MyInterceptor myInterceptor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; MyMvcConfig&lt;/span&gt;&lt;span&gt;(MyInterceptor &lt;/span&gt;&lt;span&gt;myInterceptor&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.myInterceptor &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; myInterceptor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; addInterceptors&lt;/span&gt;&lt;span&gt;(InterceptorRegistry &lt;/span&gt;&lt;span&gt;registry&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        registry.&lt;/span&gt;&lt;span&gt;addInterceptor&lt;/span&gt;&lt;span&gt;(myInterceptor)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;addPathPatterns&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/**&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;excludePathPatterns&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/login&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;/error&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MyInterceptor&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; HandlerInterceptor&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 拦截逻辑&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;整合 Druid 数据源&lt;a href=&quot;#整合-druid-数据源&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;使用 Spring Boot 3 对应的 Druid Starter 时，不需要再重复引入普通 &lt;code&gt;druid&lt;/code&gt; 依赖。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-jdbc&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.alibaba&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;druid-spring-boot-3-starter&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.2.23&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;runtime&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;spring&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  datasource&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;com.alibaba.druid.pool.DruidDataSource&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    druid&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      url&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;jdbc:mysql://localhost:3306/java2601?serverTimezone=UTC&amp;amp;characterEncoding=utf8&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      username&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      password&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      driver-class-name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;com.mysql.cj.jdbc.Driver&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      max-active&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      min-idle&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      initial-size&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      max-wait&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;10000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;测试数据源&lt;a href=&quot;#测试数据源&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;SpringBootTest&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;class&lt;/span&gt;&lt;span&gt; SpringBootDemoApplicationTests&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Autowired&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; JdbcTemplate jdbcTemplate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    void&lt;/span&gt;&lt;span&gt; testJdbcTemplate&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        List&amp;lt;Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; list &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                jdbcTemplate.&lt;/span&gt;&lt;span&gt;queryForList&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;SELECT * FROM t_user&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(list);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(jdbcTemplate.&lt;/span&gt;&lt;span&gt;getDataSource&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;数据库账号和密码不应提交到公开仓库。实际项目可通过环境变量、外部配置文件或密钥管理服务提供敏感配置。&lt;/p&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:框架</category><category>tag:Spring Boot</category></item><item><title>Spring</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/framework/spring</link><guid isPermaLink="false">learn/hyxy/framework/spring</guid><description>Spring
IoC 与依赖注入
IoC 的核心思想
IoC 是控制反转。传统代码通常由对象自己创建依赖对象；使用 Spring 后，对象的创建、配置和依赖关系由 Spring IoC 容器统一管理。
依赖注入是 IoC 的一种具体实现方式。对象只声明自己需要哪些依赖，容器在创建 Bean</description><pubDate>Thu, 30 Jul 2026 11:32:31 GMT</pubDate><content:encoded>&lt;h1&gt;Spring&lt;a href=&quot;#spring&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;IoC 与依赖注入&lt;a href=&quot;#ioc-与依赖注入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;IoC 的核心思想&lt;a href=&quot;#ioc-的核心思想&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;IoC 是控制反转。传统代码通常由对象自己创建依赖对象；使用 Spring 后，对象的创建、配置和依赖关系由 Spring IoC 容器统一管理。&lt;/p&gt;
&lt;p&gt;依赖注入是 IoC 的一种具体实现方式。对象只声明自己需要哪些依赖，容器在创建 Bean 时把相应对象注入进去。&lt;/p&gt;
&lt;p&gt;例如，&lt;code&gt;Driver&lt;/code&gt; 依赖 &lt;code&gt;Vehicle&lt;/code&gt;。业务类不再自行执行 &lt;code&gt;new Car()&lt;/code&gt;，而是由容器创建 &lt;code&gt;Car&lt;/code&gt;，再注入 &lt;code&gt;Driver&lt;/code&gt;。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; Vehicle&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    void&lt;/span&gt;&lt;span&gt; run&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Car&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; Vehicle&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String name;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setName&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; name;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; run&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(name &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;正在行驶&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Driver&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String name;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Vehicle vehicle;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setName&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; name;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setVehicle&lt;/span&gt;&lt;span&gt;(Vehicle &lt;/span&gt;&lt;span&gt;vehicle&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.vehicle &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; vehicle;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; drive&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(name &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;准备出发&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        vehicle.&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Spring 项目搭建&lt;a href=&quot;#spring-项目搭建&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;创建 Maven 工程&lt;a href=&quot;#创建-maven-工程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在 &lt;code&gt;pom.xml&lt;/code&gt; 中引入 &lt;code&gt;spring-context&lt;/code&gt;。以下版本仅对应原课程示例环境：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-context&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;5.3.20&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;创建核心配置文件&lt;a href=&quot;#创建核心配置文件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;在资源目录中创建 &lt;code&gt;applicationContext.xml&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;?&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span&gt; encoding&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;beans&lt;/span&gt;&lt;span&gt; xmlns&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://www.springframework.org/schema/beans&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       xmlns:xsi&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       xsi:schemaLocation&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           http://www.springframework.org/schema/beans&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           https://www.springframework.org/schema/beans/spring-beans.xsd&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;beans&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;启动容器&lt;a href=&quot;#启动容器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;ApplicationContext context &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        new&lt;/span&gt;&lt;span&gt; ClassPathXmlApplicationContext&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;applicationContext.xml&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Driver driver &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; context.&lt;/span&gt;&lt;span&gt;getBean&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;driver&quot;&lt;/span&gt;&lt;span&gt;, Driver.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;driver.&lt;/span&gt;&lt;span&gt;drive&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;XML 配置 Bean&lt;a href=&quot;#xml-配置-bean&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;注册 Bean&lt;a href=&quot;#注册-bean&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;driver&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Driver&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;car&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Car&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;id&lt;/code&gt; 是 Bean 在容器中的名称，&lt;code&gt;class&lt;/code&gt; 是实现类的全限定类名。&lt;/p&gt;
&lt;h3&gt;Setter 注入&lt;a href=&quot;#setter-注入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;car&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Car&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;小轿车&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;driver&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Driver&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;老张&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;vehicle&quot;&lt;/span&gt;&lt;span&gt; ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;car&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;value&lt;/code&gt; 用于注入简单值，&lt;code&gt;ref&lt;/code&gt; 用于引用容器中的另一个 Bean。&lt;/p&gt;
&lt;p&gt;Setter 注入要求属性存在对应的 Setter 方法。Getter 方法不是完成注入的必要条件，但通常会按 JavaBean 规范一并提供。&lt;/p&gt;
&lt;h3&gt;构造器注入&lt;a href=&quot;#构造器注入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Driver&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; String name;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; Vehicle vehicle;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Driver&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;, Vehicle &lt;/span&gt;&lt;span&gt;vehicle&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.name &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; name;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.vehicle &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; vehicle;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;driver&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Driver&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;constructor-arg&lt;/span&gt;&lt;span&gt; index&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;0&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;老张&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;constructor-arg&lt;/span&gt;&lt;span&gt; index&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1&quot;&lt;/span&gt;&lt;span&gt; ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;car&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;也可以通过 &lt;code&gt;name&lt;/code&gt; 或 &lt;code&gt;type&lt;/code&gt; 指定参数，但构造器重载较多时，使用 &lt;code&gt;index&lt;/code&gt; 或明确的参数名更容易避免歧义。&lt;/p&gt;
&lt;p&gt;构造器注入适合必需依赖，可以保证对象创建完成后处于可用状态。&lt;/p&gt;
&lt;h2&gt;Bean 作用域&lt;a href=&quot;#bean-作用域&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Spring Bean 默认是单例作用域，即同一个容器中，同一 Bean 定义通常只创建一个实例。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;driver&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Driver&quot;&lt;/span&gt;&lt;span&gt; scope&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;singleton&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;原型作用域会在每次获取 Bean 时创建新对象：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;driver&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Driver&quot;&lt;/span&gt;&lt;span&gt; scope&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;prototype&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常用作用域包括：&lt;/p&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;作用域&lt;/th&gt;&lt;th&gt;含义&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;singleton&lt;/code&gt;&lt;/td&gt;&lt;td&gt;每个 Spring 容器中通常只有一个实例。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;prototype&lt;/code&gt;&lt;/td&gt;&lt;td&gt;每次获取时创建一个新实例。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;request&lt;/code&gt;&lt;/td&gt;&lt;td&gt;每个 HTTP 请求一个实例。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;session&lt;/code&gt;&lt;/td&gt;&lt;td&gt;每个 HTTP Session 一个实例。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;application&lt;/code&gt;&lt;/td&gt;&lt;td&gt;每个 Web 应用一个实例。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Web 作用域需要在 Web 应用上下文中使用。&lt;/p&gt;
&lt;h2&gt;自动装配&lt;a href=&quot;#自动装配&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;XML 按名称装配&lt;a href=&quot;#xml-按名称装配&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;driver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Driver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      autowire&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;byName&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;老张&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;vehicle&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Car&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;小轿车&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;byName&lt;/code&gt; 会根据属性名查找同名 Bean。上例要求 &lt;code&gt;Driver&lt;/code&gt; 的属性名为 &lt;code&gt;vehicle&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;XML 按类型装配&lt;a href=&quot;#xml-按类型装配&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;driver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Driver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      autowire&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;byType&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;老张&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;car&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Car&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;byType&lt;/code&gt; 会根据属性类型查找 Bean。若同类型候选对象有多个，容器无法确定唯一依赖，通常会抛出异常。&lt;/p&gt;
&lt;p&gt;XML 自动装配可用于学习原理，但实际项目更常使用构造器注入配合注解或 Java 配置。&lt;/p&gt;
&lt;h2&gt;循环依赖&lt;a href=&quot;#循环依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;循环依赖是指 Bean 之间形成相互依赖，例如 &lt;code&gt;A&lt;/code&gt; 依赖 &lt;code&gt;B&lt;/code&gt;，同时 &lt;code&gt;B&lt;/code&gt; 又依赖 &lt;code&gt;A&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;Spring 可以解决部分单例 Bean 的 Setter 或字段注入循环依赖，但不能保证解决所有循环依赖。以下情况通常无法自动解决：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;构造器之间相互依赖。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prototype&lt;/code&gt; Bean 之间循环依赖。&lt;/li&gt;
&lt;li&gt;某些代理、初始化过程或自定义生命周期逻辑导致的循环依赖。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;循环依赖通常反映类职责划分不合理，应优先通过重新设计依赖关系解决，而不是依赖容器兜底。&lt;/p&gt;
&lt;h2&gt;Bean 生命周期&lt;a href=&quot;#bean-生命周期&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;XML 生命周期方法&lt;a href=&quot;#xml-生命周期方法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;driver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Driver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      init-method&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;init&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      destroy-method&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;destroy&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Driver&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; init&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;初始化 Driver&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; destroy&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;销毁 Driver&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;容器关闭时会调用单例 Bean 的销毁回调。Spring 不会自动完整管理原型 Bean 的销毁过程，原型对象使用完毕后通常由调用方负责清理资源。&lt;/p&gt;
&lt;h3&gt;注解生命周期方法&lt;a href=&quot;#注解生命周期方法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Spring 5 常见项目使用 &lt;code&gt;javax.annotation&lt;/code&gt;，Spring 6 和 Spring Boot 3 使用 &lt;code&gt;jakarta.annotation&lt;/code&gt;。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;PostConstruct&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; init&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;初始化 Driver&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;PreDestroy&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; destroy&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;销毁 Driver&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;初始化流程概览&lt;a href=&quot;#初始化流程概览&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;单例 Bean 的典型初始化流程可概括为：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;实例化 Bean。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;注入属性和依赖。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;调用相关 &lt;code&gt;Aware&lt;/code&gt; 接口。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;执行 &lt;code&gt;BeanPostProcessor&lt;/code&gt; 的前置处理。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;执行初始化回调，例如 &lt;code&gt;@PostConstruct&lt;/code&gt;、&lt;code&gt;InitializingBean&lt;/code&gt; 或自定义 &lt;code&gt;init-method&lt;/code&gt;。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;执行 &lt;code&gt;BeanPostProcessor&lt;/code&gt; 的后置处理，AOP 代理通常在此阶段创建。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Bean 进入可用状态。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;容器关闭时，会执行相应销毁回调。&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;BeanFactory&lt;/code&gt; 与 &lt;code&gt;FactoryBean&lt;/code&gt;&lt;a href=&quot;#beanfactory-与-factorybean&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;BeanFactory&lt;/code&gt;&lt;a href=&quot;#beanfactory&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;BeanFactory&lt;/code&gt; 是 Spring IoC 容器的基础接口，负责 Bean 的创建、获取和依赖管理。&lt;code&gt;ApplicationContext&lt;/code&gt; 在其基础上增加了事件、国际化、资源加载等功能。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;FactoryBean&lt;/code&gt;&lt;a href=&quot;#factorybean&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;FactoryBean&amp;lt;T&amp;gt;&lt;/code&gt; 本身是一个 Bean，但调用方通过普通 Bean 名称获取到的通常是它生产的对象。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; SqlSessionFactoryBean&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; FactoryBean&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;SqlSessionFactory&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String configLocation;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setConfigLocation&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;configLocation&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.configLocation &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; configLocation;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; SqlSessionFactory &lt;/span&gt;&lt;span&gt;getObject&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Exception {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; (InputStream inputStream &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                     Resources.&lt;/span&gt;&lt;span&gt;getResourceAsStream&lt;/span&gt;&lt;span&gt;(configLocation)) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; SqlSessionFactoryBuilder&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;(inputStream);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Class&amp;lt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;getObjectType&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; SqlSessionFactory.class;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; isSingleton&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;sqlSessionFactory&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.SqlSessionFactoryBean&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;configLocation&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mybatis-config.xml&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;获取 &lt;code&gt;sqlSessionFactory&lt;/code&gt; 时得到的是 &lt;code&gt;FactoryBean&lt;/code&gt; 生产的对象；若要获取工厂 Bean 本身，需要在名称前加 &lt;code&gt;&amp;amp;&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;Bean 注册方式&lt;a href=&quot;#bean-注册方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Spring 常见的 Bean 注册方式包括 XML、组件扫描和 Java 配置。&lt;/p&gt;
&lt;h3&gt;XML 注册&lt;a href=&quot;#xml-注册&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;car&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.Car&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;XML 适合集中查看配置，也便于注册无法修改源码的第三方类，但配置量较大时会比较繁琐。&lt;/p&gt;
&lt;h3&gt;注解与组件扫描&lt;a href=&quot;#注解与组件扫描&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;先在配置文件中开启扫描：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;context:component-scan&lt;/span&gt;&lt;span&gt; base-package&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;再用组件注解标记类：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Car&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;常用分层注解包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@Controller&lt;/code&gt;：控制层组件。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@Service&lt;/code&gt;：业务层组件。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@Repository&lt;/code&gt;：数据访问层组件。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@Component&lt;/code&gt;：通用组件。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些注解都能把类注册为 Spring Bean，分层名称主要用于表达职责；部分注解还可能参与框架的异常转换等机制。&lt;/p&gt;
&lt;h2&gt;依赖注入注解&lt;a href=&quot;#依赖注入注解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;@Autowired&lt;/code&gt;&lt;a href=&quot;#autowired&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;@Autowired&lt;/code&gt; 主要按类型查找依赖。若存在多个同类型 Bean，可结合 &lt;code&gt;@Qualifier&lt;/code&gt; 或 &lt;code&gt;@Primary&lt;/code&gt; 消除歧义。&lt;/p&gt;
&lt;p&gt;推荐使用构造器注入：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; DriverService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; Vehicle vehicle;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; DriverService&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;Qualifier&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;car&quot;&lt;/span&gt;&lt;span&gt;) Vehicle &lt;/span&gt;&lt;span&gt;vehicle&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.vehicle &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; vehicle;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;只有一个构造器时，通常可以省略构造器上的 &lt;code&gt;@Autowired&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;@Qualifier&lt;/code&gt;&lt;a href=&quot;#qualifier&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;car&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Car&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; Vehicle&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;bus&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Bus&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; Vehicle&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; DriverService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; Vehicle vehicle;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; DriverService&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;Qualifier&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;bus&quot;&lt;/span&gt;&lt;span&gt;) Vehicle &lt;/span&gt;&lt;span&gt;vehicle&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.vehicle &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; vehicle;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;@Primary&lt;/code&gt;&lt;a href=&quot;#primary&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Primary&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Car&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; Vehicle&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同类型候选 Bean 有多个时，&lt;code&gt;@Primary&lt;/code&gt; 标记的 Bean 会作为默认选择。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;@Resource&lt;/code&gt;&lt;a href=&quot;#resource&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;@Resource&lt;/code&gt; 属于 Jakarta 或 Java 标准注解，通常先按名称匹配，再按类型匹配。它可以通过 &lt;code&gt;name&lt;/code&gt; 显式指定 Bean 名称。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Resource&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;car&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; Vehicle vehicle;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;@Value&lt;/code&gt;&lt;a href=&quot;#value&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;@Value&lt;/code&gt; 可注入简单配置值或 Spring 表达式。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Value&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;${car.name:默认车辆}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; String carName;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;复杂配置对象更适合使用 &lt;code&gt;@ConfigurationProperties&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;@Scope&lt;/code&gt;&lt;a href=&quot;#scope&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Scope&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;prototype&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Driver&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Java 配置&lt;a href=&quot;#java-配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;定义配置类&lt;a href=&quot;#定义配置类&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MyConfig&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Car &lt;/span&gt;&lt;span&gt;car&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Car car &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Car&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        car.&lt;/span&gt;&lt;span&gt;setName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;小轿车&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; car;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Scope&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;prototype&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Driver &lt;/span&gt;&lt;span&gt;driver&lt;/span&gt;&lt;span&gt;(Car &lt;/span&gt;&lt;span&gt;car&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Driver driver &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Driver&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        driver.&lt;/span&gt;&lt;span&gt;setName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;老张&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        driver.&lt;/span&gt;&lt;span&gt;setVehicle&lt;/span&gt;&lt;span&gt;(car);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; driver;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;@Configuration&lt;/code&gt; 表明该类是配置类，&lt;code&gt;@Bean&lt;/code&gt; 方法的返回对象会注册到容器中。方法参数会由容器自动注入。&lt;/p&gt;
&lt;p&gt;通过方法参数表达依赖比在方法内部直接调用其他 &lt;code&gt;@Bean&lt;/code&gt; 方法更清晰，也更容易测试。&lt;/p&gt;
&lt;h3&gt;启动 Java 配置容器&lt;a href=&quot;#启动-java-配置容器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;ApplicationContext context &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        new&lt;/span&gt;&lt;span&gt; AnnotationConfigApplicationContext&lt;/span&gt;&lt;span&gt;(MyConfig.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Driver driver &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; context.&lt;/span&gt;&lt;span&gt;getBean&lt;/span&gt;&lt;span&gt;(Driver.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;driver.&lt;/span&gt;&lt;span&gt;drive&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;代理模式&lt;a href=&quot;#代理模式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;代理模式包含目标对象、代理对象和双方共同遵循的抽象契约。代理对象在调用目标方法前后增加通用逻辑，例如日志、权限校验或事务管理。&lt;/p&gt;
&lt;h3&gt;静态代理&lt;a href=&quot;#静态代理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; HouseService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    void&lt;/span&gt;&lt;span&gt; rentHouse&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Owner&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; HouseService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; rentHouse&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;签合同并收款&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Agent&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; HouseService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; HouseService target;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Agent&lt;/span&gt;&lt;span&gt;(HouseService &lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.target &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; target;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; rentHouse&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;寻找房源并协商价格&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        target.&lt;/span&gt;&lt;span&gt;rentHouse&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;静态代理需要为不同目标类型编写对应代理类，重复代码较多。&lt;/p&gt;
&lt;h3&gt;JDK 动态代理&lt;a href=&quot;#jdk-动态代理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;JDK 动态代理基于接口创建代理对象。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;HouseService target &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Owner&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;HouseService proxy &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (HouseService) Proxy.&lt;/span&gt;&lt;span&gt;newProxyInstance&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        target.&lt;/span&gt;&lt;span&gt;getClass&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;getClassLoader&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        target.&lt;/span&gt;&lt;span&gt;getClass&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;getInterfaces&lt;/span&gt;&lt;span&gt;(),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        (proxyObject, method, args) &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;调用前处理&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                return&lt;/span&gt;&lt;span&gt; method.&lt;/span&gt;&lt;span&gt;invoke&lt;/span&gt;&lt;span&gt;(target, args);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            } &lt;/span&gt;&lt;span&gt;finally&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;调用后处理&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;proxy.&lt;/span&gt;&lt;span&gt;rentHouse&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;CGLIB 动态代理&lt;a href=&quot;#cglib-动态代理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;CGLIB 通过生成目标类的子类创建代理，不要求目标类实现接口。目标类不能是 &lt;code&gt;final&lt;/code&gt;，需要代理的方法也不能是 &lt;code&gt;final&lt;/code&gt;。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; DaoMethodInterceptor&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; MethodInterceptor&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Object &lt;/span&gt;&lt;span&gt;intercept&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Object &lt;/span&gt;&lt;span&gt;proxy&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Method &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Object&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            MethodProxy &lt;/span&gt;&lt;span&gt;methodProxy&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Throwable {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;开启事务&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Object result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; methodProxy.&lt;/span&gt;&lt;span&gt;invokeSuper&lt;/span&gt;&lt;span&gt;(proxy, args);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;提交事务&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            return&lt;/span&gt;&lt;span&gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (Throwable &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;回滚事务&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            throw&lt;/span&gt;&lt;span&gt; e;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Enhancer enhancer &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Enhancer&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;enhancer.&lt;/span&gt;&lt;span&gt;setSuperclass&lt;/span&gt;&lt;span&gt;(EmpDao.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;enhancer.&lt;/span&gt;&lt;span&gt;setCallback&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; DaoMethodInterceptor&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpDao empDao &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (EmpDao) enhancer.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;empDao.&lt;/span&gt;&lt;span&gt;save&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不要使用已经过时的 &lt;code&gt;Class.newInstance()&lt;/code&gt;。需要通过反射创建对象时，应使用 &lt;code&gt;getDeclaredConstructor().newInstance()&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;AOP&lt;a href=&quot;#aop&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;AOP 是面向切面编程，用于把日志、事务、权限等横切逻辑从业务代码中分离出来。&lt;/p&gt;
&lt;h3&gt;常用术语&lt;a href=&quot;#常用术语&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;连接点：程序执行过程中可被增强的位置，例如方法调用。&lt;/li&gt;
&lt;li&gt;切入点：用于筛选需要增强的连接点。&lt;/li&gt;
&lt;li&gt;通知：在目标方法前后执行的增强逻辑。&lt;/li&gt;
&lt;li&gt;切面：切入点和通知的组合。&lt;/li&gt;
&lt;li&gt;目标对象：被增强的业务对象。&lt;/li&gt;
&lt;li&gt;代理对象：应用增强逻辑后的对象。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;引入依赖&lt;a href=&quot;#引入依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-aspects&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;5.3.20&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;定义切面&lt;a href=&quot;#定义切面&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Aspect&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; LogAspect&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Pointcut&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;execution(* com.hyxy.service..*(..))&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; serviceMethod&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Before&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;serviceMethod()&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; before&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;执行方法前记录日志&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;AfterReturning&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;pointcut&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;serviceMethod()&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;returning&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;result&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; afterReturning&lt;/span&gt;&lt;span&gt;(Object &lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;方法正常返回：&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; result);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;AfterThrowing&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;pointcut&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;serviceMethod()&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;throwing&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;exception&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; afterThrowing&lt;/span&gt;&lt;span&gt;(Throwable &lt;/span&gt;&lt;span&gt;exception&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;方法发生异常：&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; exception.&lt;/span&gt;&lt;span&gt;getMessage&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;After&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;serviceMethod()&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; after&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;方法结束&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;开启注解 AOP：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;aop:aspectj-autoproxy&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;@After&lt;/code&gt; 类似 &lt;code&gt;finally&lt;/code&gt;，无论方法正常返回还是抛出异常都会执行；只有正常返回时才执行 &lt;code&gt;@AfterReturning&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;Spring 事务概述&lt;a href=&quot;#spring-事务概述&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Spring 声明式事务基于 AOP。常用事务属性包括传播行为、隔离级别、超时、只读和回滚规则。&lt;/p&gt;
&lt;p&gt;常见传播行为：&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;传播行为&lt;/th&gt;&lt;th&gt;含义&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;REQUIRED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;有事务则加入，没有事务则创建。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;REQUIRES_NEW&lt;/code&gt;&lt;/td&gt;&lt;td&gt;总是创建新事务，并暂停当前事务。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SUPPORTS&lt;/code&gt;&lt;/td&gt;&lt;td&gt;有事务则加入，没有事务则非事务运行。&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;NESTED&lt;/code&gt;&lt;/td&gt;&lt;td&gt;在支持保存点的环境中使用嵌套事务范围。&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; UserService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;rollbackFor&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Exception.class)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; saveUser&lt;/span&gt;&lt;span&gt;(User &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Exception {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 数据库操作&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;默认情况下，Spring 对 &lt;code&gt;RuntimeException&lt;/code&gt; 和 &lt;code&gt;Error&lt;/code&gt; 回滚，对普通受检异常不自动回滚。需要对受检异常回滚时，应配置 &lt;code&gt;rollbackFor&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;Spring 与 MyBatis 整合&lt;a href=&quot;#spring-与-mybatis-整合&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;整合目标是由 Spring 管理数据源、&lt;code&gt;SqlSessionFactory&lt;/code&gt;、Mapper 代理和事务。&lt;/p&gt;
&lt;h3&gt;Maven 依赖&lt;a href=&quot;#maven-依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;以下版本为原课程示例组合：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;maven.compiler.source&lt;/span&gt;&lt;span&gt;&amp;gt;11&amp;lt;/&lt;/span&gt;&lt;span&gt;maven.compiler.source&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;maven.compiler.target&lt;/span&gt;&lt;span&gt;&amp;gt;11&amp;lt;/&lt;/span&gt;&lt;span&gt;maven.compiler.target&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;project.build.sourceEncoding&lt;/span&gt;&lt;span&gt;&amp;gt;UTF-8&amp;lt;/&lt;/span&gt;&lt;span&gt;project.build.sourceEncoding&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-context&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;5.3.20&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-jdbc&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;5.3.20&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-tx&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;5.3.20&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.5.1&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-spring&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;2.0.7&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;8.0.33&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.alibaba&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;druid&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.2.23&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;数据库配置&lt;a href=&quot;#数据库配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;jdbc.driverClassName&lt;/span&gt;&lt;span&gt;=com.mysql.cj.jdbc.Driver&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.url&lt;/span&gt;&lt;span&gt;=jdbc:mysql://localhost:3306/java2601?&lt;/span&gt;&lt;span&gt;serverTimezone&lt;/span&gt;&lt;span&gt;=UTC&amp;amp;&lt;/span&gt;&lt;span&gt;characterEncoding&lt;/span&gt;&lt;span&gt;=utf8&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.username&lt;/span&gt;&lt;span&gt;=root&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.password&lt;/span&gt;&lt;span&gt;=root&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.maxActive&lt;/span&gt;&lt;span&gt;=300&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.initialSize&lt;/span&gt;&lt;span&gt;=2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.maxWait&lt;/span&gt;&lt;span&gt;=60000&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.minIdle&lt;/span&gt;&lt;span&gt;=1&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Spring 配置&lt;a href=&quot;#spring-配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;?&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span&gt; encoding&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;beans&lt;/span&gt;&lt;span&gt; xmlns&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://www.springframework.org/schema/beans&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       xmlns:xsi&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       xmlns:context&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://www.springframework.org/schema/context&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       xmlns:tx&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://www.springframework.org/schema/tx&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       xmlns:mybatis-spring&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://mybatis.org/schema/mybatis-spring&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       xsi:schemaLocation&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           http://www.springframework.org/schema/beans&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           https://www.springframework.org/schema/beans/spring-beans.xsd&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           http://www.springframework.org/schema/context&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           https://www.springframework.org/schema/context/spring-context.xsd&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           http://www.springframework.org/schema/tx&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           https://www.springframework.org/schema/tx/spring-tx.xsd&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           http://mybatis.org/schema/mybatis-spring&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;           http://mybatis.org/schema/mybatis-spring.xsd&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;context:property-placeholder&lt;/span&gt;&lt;span&gt; location&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;classpath:db.properties&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;context:component-scan&lt;/span&gt;&lt;span&gt; base-package&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.alibaba.druid.pool.DruidDataSource&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;driverClassName&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.driverClassName}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;url&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.url}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;username&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.username}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;password&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.password}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;maxActive&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.maxActive}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;initialSize&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.initialSize}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;maxWait&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.maxWait}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;minIdle&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.minIdle}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;sqlSessionFactory&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;          class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.spring.SqlSessionFactoryBean&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt; ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mapperLocations&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                  value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;classpath*:com/hyxy/mapper/*.xml&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;typeAliasesPackage&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.po&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;mybatis-spring:scan&lt;/span&gt;&lt;span&gt; base-package&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.hyxy.mapper&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;transactionManager&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;          class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt; ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;tx:annotation-driven&lt;/span&gt;&lt;span&gt; transaction-manager&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;transactionManager&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;beans&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;SqlSessionFactoryBean&lt;/code&gt; 负责创建 MyBatis 的 &lt;code&gt;SqlSessionFactory&lt;/code&gt;，Mapper 扫描器会为接口创建代理并注册到 Spring 容器。&lt;/p&gt;
&lt;h3&gt;Mapper 与 Service&lt;a href=&quot;#mapper-与-service&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; UserMapper&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; insert&lt;/span&gt;&lt;span&gt;(User &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; UserService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; UserMapper userMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; UserService&lt;/span&gt;&lt;span&gt;(UserMapper &lt;/span&gt;&lt;span&gt;userMapper&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.userMapper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; userMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;rollbackFor&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Exception.class)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; save&lt;/span&gt;&lt;span&gt;(User &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Exception {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        userMapper.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(user);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;业务层只需要注入 Mapper，不应自行创建 &lt;code&gt;SqlSession&lt;/code&gt;。事务由 Spring 管理时，也不应在 Mapper 或 Service 中手动调用 &lt;code&gt;commit()&lt;/code&gt;。&lt;/p&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:框架</category><category>tag:Spring</category></item><item><title>MyBatis 全套知识体系完全指南</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/framework/mybatis-quan-tao-zhi-shi-ti-xi-wan-quan-zhi-nan</link><guid isPermaLink="false">learn/hyxy/framework/mybatis-quan-tao-zhi-shi-ti-xi-wan-quan-zhi-nan</guid><description>MyBatis 全套知识体系完全指南
本文档全面覆盖 MyBatis 的理论知识与指令操作，从基础概念到高级实战，无遗漏。
MyBatis 概述
什么是 MyBatis
MyBatis 是一款 SQL 映射与持久层框架。它允许开发者自行编写</description><pubDate>Thu, 30 Jul 2026 11:31:21 GMT</pubDate><content:encoded>&lt;h1&gt;MyBatis 全套知识体系完全指南&lt;a href=&quot;#mybatis-全套知识体系完全指南&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;本文档全面覆盖 MyBatis 的理论知识与指令操作，从基础概念到高级实战，无遗漏。&lt;/p&gt;
&lt;h2&gt;MyBatis 概述&lt;a href=&quot;#mybatis-概述&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;什么是 MyBatis&lt;a href=&quot;#什么是-mybatis&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MyBatis 是一款 SQL 映射与持久层框架。它允许开发者自行编写 SQL，并负责参数绑定、结果映射、事务协作等重复工作。MyBatis 常被称为“半自动 ORM”，但它不会像全自动 ORM 框架那样根据实体关系自动生成全部 SQL。&lt;/p&gt;
&lt;p&gt;MyBatis 前身是 iBatis，2010 年由 Apache 迁移到 Google Code 并更名为 MyBatis，后迁移至 GitHub。&lt;/p&gt;
&lt;h3&gt;MyBatis 的定位&lt;a href=&quot;#mybatis-的定位&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;特性&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;JDBC&lt;/th&gt;&lt;th&gt;MyBatis&lt;/th&gt;&lt;th&gt;Hibernate (JPA)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;SQL&lt;/strong&gt; 控制&lt;/td&gt;&lt;td&gt;完全手动&lt;/td&gt;&lt;td&gt;半自动（手写 &lt;strong&gt;SQL&lt;/strong&gt;，自动映射）&lt;/td&gt;&lt;td&gt;全自动（自动生成 &lt;strong&gt;SQL&lt;/strong&gt;）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;学习成本&lt;/td&gt;&lt;td&gt;高（大量样板代码）&lt;/td&gt;&lt;td&gt;中&lt;/td&gt;&lt;td&gt;高&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;灵活性&lt;/td&gt;&lt;td&gt;最高&lt;/td&gt;&lt;td&gt;高&lt;/td&gt;&lt;td&gt;较低&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;性能可控&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;td&gt;较难（需调优）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;数据库移植性&lt;/td&gt;&lt;td&gt;差&lt;/td&gt;&lt;td&gt;中&lt;/td&gt;&lt;td&gt;高&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;适合场景&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;td&gt;复杂 &lt;strong&gt;SQL、高性能需求&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;快速开发、简单 CRUD&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;MyBatis 的核心特性&lt;a href=&quot;#mybatis-的核心特性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; ┌────────────────────────────────────────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │              MyBatis 核心特性                        │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├──────────────┬──────────────┬─────────────────────┤&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   SQL 映射    │  动态 SQL    │  高级映射            │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├──────────────┼──────────────┼─────────────────────┤&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │ XML/注解配置  │ 条件拼接      │ 一对一/一对多/多对多  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │ 参数自动绑定  │ 循环遍历      │ 嵌套结果/嵌套查询     │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │ 结果自动映射  │ SQL 片段复用  │ 鉴别器（discriminator）│&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├──────────────┼──────────────┼─────────────────────┤&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   缓存机制    │  插件机制     │  扩展能力            │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├──────────────┼──────────────┼─────────────────────┤&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│ 一级缓存      │ 拦截器        │ TypeHandler          │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│ 二级缓存      │ 分页插件      │ ObjectFactory        │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│ 第三方缓存    │ SQL 审计      │ 语言驱动             │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└──────────────┴──────────────┴─────────────────────┘&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;MyBatis 架构&lt;a href=&quot;#mybatis-架构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;                     ┌─────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                     │   应用程序层      │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                     │  (Service/DAO)   │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                     └────────┬────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                              │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                     ┌────────▼────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                     │  SqlSession 接口  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                     │ (selectOne/list  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                     │  insert/update   │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    │  delete/commit)  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    └────────┬────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                             │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    ┌────────▼────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    │  Executor 执行器  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    │  (Simple/Reuse   │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    │   Batch)         │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    └────────┬────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                             │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;              ┌──────────────┼──────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;              │              │              │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     ┌────────▼───┐  ┌──────▼─────┐  ┌────▼────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     │ Statement  │  │ Parameter  │  │  ResultSet  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     │ Handler    │  │ Handler    │  │  Handler    │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     │(SQL预处理)  │  │(参数绑定)   │  │(结果映射)    │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     └────────┬───┘  └────────────┘  └─────────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;              │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     ┌────────▼───┐&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     │   JDBC     │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     │  数据库     │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     └────────────┘&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;MyBatis 版本&lt;a href=&quot;#mybatis-版本&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MyBatis 3 是目前课程和实际项目中常用的主版本系列。本文示例使用 &lt;code&gt;3.5.15&lt;/code&gt;，版本号仅用于保证示例可复现；实际项目应以依赖管理中确定的版本为准，并在升级时查阅对应版本的发布说明。&lt;/p&gt;
&lt;h2&gt;快速入门&lt;a href=&quot;#快速入门&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;示例数据库&lt;a href=&quot;#示例数据库&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;本文档统一使用以下示例数据库：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; -- 部门表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; dept&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     dept_id   &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt; PRIMARY KEY&lt;/span&gt;&lt;span&gt; AUTO_INCREMENT,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     dept_name &lt;/span&gt;&lt;span&gt;VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     location&lt;/span&gt;&lt;span&gt;  VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; -- 员工表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; emp&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    emp_id     &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt; PRIMARY KEY&lt;/span&gt;&lt;span&gt; AUTO_INCREMENT,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    emp_name   &lt;/span&gt;&lt;span&gt;VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    email      &lt;/span&gt;&lt;span&gt;VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    salary     &lt;/span&gt;&lt;span&gt;DECIMAL&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    dept_id    &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    hire_date  &lt;/span&gt;&lt;span&gt;DATE&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    status&lt;/span&gt;&lt;span&gt;     TINYINT&lt;/span&gt;&lt;span&gt; DEFAULT&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt;,  &lt;/span&gt;&lt;span&gt;-- 1:在职 0:离职&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    FOREIGN KEY&lt;/span&gt;&lt;span&gt; (dept_id) &lt;/span&gt;&lt;span&gt;REFERENCES&lt;/span&gt;&lt;span&gt; dept(dept_id)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-- 项目表（多对多）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; project&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    project_id   &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt; PRIMARY KEY&lt;/span&gt;&lt;span&gt; AUTO_INCREMENT,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    project_name &lt;/span&gt;&lt;span&gt;VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;NOT NULL&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    budget       &lt;/span&gt;&lt;span&gt;DECIMAL&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-- 员工-项目关联表（多对多）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; emp_project&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    emp_id     &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    project_id &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    role&lt;/span&gt;&lt;span&gt;       VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    PRIMARY KEY&lt;/span&gt;&lt;span&gt; (emp_id, project_id),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    FOREIGN KEY&lt;/span&gt;&lt;span&gt; (emp_id) &lt;/span&gt;&lt;span&gt;REFERENCES&lt;/span&gt;&lt;span&gt; emp(emp_id),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    FOREIGN KEY&lt;/span&gt;&lt;span&gt; (project_id) &lt;/span&gt;&lt;span&gt;REFERENCES&lt;/span&gt;&lt;span&gt; project(project_id)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Maven 依赖&lt;a href=&quot;#maven-依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- MyBatis 核心 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.5.15&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- MySQL 驱动 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;8.3.0&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 日志 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.slf4j&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;slf4j-api&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;2.0.12&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;ch.qos.logback&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;logback-classic&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.4.14&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- Lombok --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.projectlombok&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;lombok&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.18.30&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;provided&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;实体类&lt;a href=&quot;#实体类&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.entity;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; lombok.Data;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.math.BigDecimal;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.time.LocalDate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String email;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; BigDecimal salary;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer deptId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDate hireDate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer status;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 关联对象&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Dept dept;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 关联集合（多对多）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;Project&lt;/span&gt;&lt;span&gt;&amp;gt; projects;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Dept&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer deptId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String deptName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String location;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 关联集合（一对多）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; emps;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Project&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer projectId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String projectName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; BigDecimal budget;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; emps;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;mybatis-config.xml&lt;a href=&quot;#mybatis-configxml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;?&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span&gt; encoding&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!&lt;/span&gt;&lt;span&gt;DOCTYPE&lt;/span&gt;&lt;span&gt; configuration&lt;/span&gt;&lt;span&gt; PUBLIC &quot;-//mybatis.org//DTD Config 3.0//EN&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;https://mybatis.org/dtd/mybatis-3-config.dtd&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 属性配置 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt; resource&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;db.properties&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 设置 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;settings&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mapUnderscoreToCamelCase&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;cacheEnabled&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;lazyLoadingEnabled&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;defaultExecutorType&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;REUSE&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;logImpl&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;SLF4J&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;settings&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 别名 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;typeAliases&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;typeAliases&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 环境配置 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;environments&lt;/span&gt;&lt;span&gt; default&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;development&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;environment&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;development&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;transactionManager&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;JDBC&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;dataSource&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;POOLED&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;driver&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.driver}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;url&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.url}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;username&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.username}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;password&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.password}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;dataSource&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;environment&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;environments&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 映射器 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;mappers&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;mappers&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;db.properties&lt;a href=&quot;#dbproperties&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;jdbc.driver&lt;/span&gt;&lt;span&gt;=com.mysql.cj.jdbc.Driver&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.url&lt;/span&gt;&lt;span&gt;=jdbc:mysql://localhost:3306/mydb?&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    useSSL&lt;/span&gt;&lt;span&gt;=false&amp;amp;&lt;/span&gt;&lt;span&gt;serverTimezone&lt;/span&gt;&lt;span&gt;=Asia/Shanghai&amp;amp;&lt;/span&gt;&lt;span&gt;characterEncoding&lt;/span&gt;&lt;span&gt;=UTF-8&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.username&lt;/span&gt;&lt;span&gt;=root&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.password&lt;/span&gt;&lt;span&gt;=root123&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Mapper 接口&lt;a href=&quot;#mapper-接口&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.mapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.example.entity.Emp;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; EmpMapper&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     // 查询所有员工&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;selectAll&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 根据 ID 查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    Emp &lt;/span&gt;&lt;span&gt;selectById&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;empId&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 插入&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; insert&lt;/span&gt;&lt;span&gt;(Emp &lt;/span&gt;&lt;span&gt;emp&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 更新&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; update&lt;/span&gt;&lt;span&gt;(Emp &lt;/span&gt;&lt;span&gt;emp&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 删除&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; deleteById&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;empId&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Mapper XML&lt;a href=&quot;#mapper-xml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;?&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span&gt; encoding&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!&lt;/span&gt;&lt;span&gt;DOCTYPE&lt;/span&gt;&lt;span&gt; mapper&lt;/span&gt;&lt;span&gt; PUBLIC &quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &quot;https://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt; namespace&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.EmpMapper&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectAll&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         SELECT * FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectById&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;int&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SELECT * FROM emp WHERE emp_id = #{empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;insert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        INSERT INTO emp (emp_name, email, salary, dept_id, hire_date, status)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        VALUES (#{empName}, #{email}, #{salary}, #{deptId}, #{hireDate}, #{status})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;update&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        UPDATE emp SET&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            emp_name = #{empName},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            email = #{email},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            salary = #{salary},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            dept_id = #{deptId},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            status = #{status}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        WHERE emp_id = #{empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deleteById&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;int&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        DELETE FROM emp WHERE emp_id = #{empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;工具类&lt;a href=&quot;#工具类&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.util;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.io.Resources;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.session.SqlSession;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.session.SqlSessionFactory;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.session.SqlSessionFactoryBuilder;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.io.InputStream;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MyBatisUtil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; SqlSessionFactory sqlSessionFactory;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    static&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            String resource &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;mybatis-config.xml&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            InputStream inputStream &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Resources.&lt;/span&gt;&lt;span&gt;getResourceAsStream&lt;/span&gt;&lt;span&gt;(resource);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            sqlSessionFactory &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; SqlSessionFactoryBuilder&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;(inputStream);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (Exception &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            throw&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; RuntimeException&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;MyBatis 初始化失败&quot;&lt;/span&gt;&lt;span&gt;, e);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; SqlSession &lt;/span&gt;&lt;span&gt;getSqlSession&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; sqlSessionFactory.&lt;/span&gt;&lt;span&gt;openSession&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; SqlSession &lt;/span&gt;&lt;span&gt;getSqlSession&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt; autoCommit&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; sqlSessionFactory.&lt;/span&gt;&lt;span&gt;openSession&lt;/span&gt;&lt;span&gt;(autoCommit);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;测试&lt;a href=&quot;#测试&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MyBatisTest&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; testSelectAll&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; (SqlSession session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; MyBatisUtil.&lt;/span&gt;&lt;span&gt;getSqlSession&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            EmpMapper mapper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;getMapper&lt;/span&gt;&lt;span&gt;(EmpMapper.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; emps &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;selectAll&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             emps.&lt;/span&gt;&lt;span&gt;forEach&lt;/span&gt;&lt;span&gt;(System.out&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;println);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; testInsert&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; (SqlSession session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; MyBatisUtil.&lt;/span&gt;&lt;span&gt;getSqlSession&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            EmpMapper mapper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;getMapper&lt;/span&gt;&lt;span&gt;(EmpMapper.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            Emp emp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            emp.&lt;/span&gt;&lt;span&gt;setEmpName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;张三&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            emp.&lt;/span&gt;&lt;span&gt;setEmail&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;zhangsan@example.com&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            emp.&lt;/span&gt;&lt;span&gt;setSalary&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; BigDecimal&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;15000&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            emp.&lt;/span&gt;&lt;span&gt;setDeptId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            emp.&lt;/span&gt;&lt;span&gt;setHireDate&lt;/span&gt;&lt;span&gt;(LocalDate.&lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            emp.&lt;/span&gt;&lt;span&gt;setStatus&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            int&lt;/span&gt;&lt;span&gt; rows &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            session.&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt;();  &lt;/span&gt;&lt;span&gt;// 必须手动提交&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;插入行数: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; rows &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;, 主键: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; emp.&lt;/span&gt;&lt;span&gt;getEmpId&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;核心配置文件（mybatis-config.xml）&lt;a href=&quot;#核心配置文件mybatis-configxml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;完整配置结构&lt;a href=&quot;#完整配置结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;?&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span&gt; encoding&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!&lt;/span&gt;&lt;span&gt;DOCTYPE&lt;/span&gt;&lt;span&gt; configuration&lt;/span&gt;&lt;span&gt; PUBLIC &quot;-//mybatis.org//DTD Config 3.0//EN&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &quot;https://mybatis.org/dtd/mybatis-3-config.dtd&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 1. 属性：引入外部 properties 文件 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt; resource&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;db.properties&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;!-- 也可以在这里定义默认属性 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;username&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;root&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 2. 设置：全局行为配置 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;settings&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 驼峰命名自动映射（emp_name → empName） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mapUnderscoreToCamelCase&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 二级缓存开关 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;cacheEnabled&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 延迟加载开关 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;lazyLoadingEnabled&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 是否按需加载（3.4.2+默认true） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;aggressiveLazyLoading&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 延迟加载触发方法 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;lazyLoadTriggerMethods&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;equals,clone,hashCode,toString&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 默认执行器类型 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;defaultExecutorType&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;REUSE&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 默认语句超时（秒） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;defaultStatementTimeout&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;30&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 默认获取大小 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;defaultFetchSize&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;100&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 本地缓存范围 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;localCacheScope&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;SESSION&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 默认事务隔离级别 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;defaultTransactionIsolationLevel&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;READ_COMMITTED&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 日志实现 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;logImpl&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;SLF4J&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 代理工厂（CGLIB/JAVASSIST） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;proxyFactory&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;JAVASSIST&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 多结果集 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;multipleResultSetsEnabled&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 列名标签前缀 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;useColumnLabel&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 使用生成的主键 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;useGeneratedKeys&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 自动映射行为 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;autoMappingBehavior&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;PARTIAL&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 自动映射未知列行为 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;autoMappingUnknownColumnBehavior&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;WARNING&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 返回行数上限 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;safeRowBoundsEnabled&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 安全的 ResultHandler --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;safeResultHandlerEnabled&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 指定 MyBatis 语言驱动 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;defaultScriptingLanguage&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.apache.ibatis.scripting.xmltags.XMLLanguageDriver&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 枚举类型默认处理器 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;defaultEnumTypeHandler&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.apache.ibatis.type.EnumTypeHandler&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- NULL 值的 JDBC 类型 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jdbcTypeForNull&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;OTHER&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;settings&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 3. 类型别名 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;typeAliases&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 单个类配置 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;typeAlias&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity.Emp&quot;&lt;/span&gt;&lt;span&gt; alias&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 包扫描（默认用类名首字母小写） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;typeAliases&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 4. 类型处理器 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;typeHandlers&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;typeHandler&lt;/span&gt;&lt;span&gt; handler&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.handler.StringListTypeHandler&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.handler&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;typeHandlers&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 5. 对象工厂 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;objectFactory&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.factory.CustomObjectFactory&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;someProperty&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;100&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;objectFactory&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 6. 插件（拦截器） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; interceptor&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.plugin.MyPagePlugin&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dialect&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mysql&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;/&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 7. 环境配置 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;environments&lt;/span&gt;&lt;span&gt; default&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;development&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;environment&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;development&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;transactionManager&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;JDBC&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;dataSource&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;POOLED&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;driver&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.driver}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;url&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.url}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;username&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.username}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;password&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.password}&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 &amp;lt;!-- 连接池配置 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;poolMaximumActiveConnections&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;10&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;poolMaximumIdleConnections&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;5&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;poolMaximumCheckoutTime&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;20000&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;poolTimeToWait&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;20000&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;poolPingEnabled&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;poolPingQuery&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;SELECT 1&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;poolPingConnectionsNotUsedFor&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;3600000&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;dataSource&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;environment&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;environment&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;production&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;transactionManager&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MANAGED&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;dataSource&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;JNDI&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;initialContext&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;java:comp/env&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jdbc/myDataSource&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;dataSource&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;environment&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;environments&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 8. 数据库厂商标识 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;databaseIdProvider&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;DB_VENDOR&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MySQL&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mysql&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Oracle&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;oracle&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;PostgreSQL&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;pg&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;databaseIdProvider&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 9. 映射器 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;mappers&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 方式一：资源路径 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt; resource&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mapper/EmpMapper.xml&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 方式二：URL --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt; url&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;file:///var/mappers/EmpMapper.xml&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 方式三：接口类 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.EmpMapper&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 方式四：包扫描 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;mappers&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;配置元素顺序&lt;a href=&quot;#配置元素顺序&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;mybatis-config.xml&lt;/code&gt; 的顶层元素必须按下列顺序出现。没有使用的元素可以省略，但不能随意交换顺序。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;1. properties&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;2. settings&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;3. typeAliases&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;4. typeHandlers&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;5. objectFactory&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;6. objectWrapperFactory&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;7. reflectorFactory&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;8. plugins&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;9. environments&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;10. databaseIdProvider&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;11. mappers&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;常用 Settings 详解&lt;a href=&quot;#常用-settings-详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;













































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;设置项&lt;/th&gt;&lt;th&gt;可选值&lt;/th&gt;&lt;th&gt;默认值&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;cacheEnabled&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;true&lt;/code&gt;、&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否全局启用映射器二级缓存&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;lazyLoadingEnabled&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;true&lt;/code&gt;、&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否启用延迟加载&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;aggressiveLazyLoading&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;true&lt;/code&gt;、&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否由任意方法调用触发对象的全部延迟属性加载&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;mapUnderscoreToCamelCase&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;true&lt;/code&gt;、&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否将下划线命名自动映射为驼峰命名&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;useGeneratedKeys&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;true&lt;/code&gt;、&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否允许 JDBC 使用自动生成主键&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;defaultExecutorType&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;SIMPLE&lt;/code&gt;、&lt;code&gt;REUSE&lt;/code&gt;、&lt;code&gt;BATCH&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;SIMPLE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;默认执行器类型&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;defaultStatementTimeout&lt;/code&gt;&lt;/td&gt;&lt;td&gt;正整数&lt;/td&gt;&lt;td&gt;未设置&lt;/td&gt;&lt;td&gt;SQL 执行超时时间，单位为秒&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;localCacheScope&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;SESSION&lt;/code&gt;、&lt;code&gt;STATEMENT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;SESSION&lt;/code&gt;&lt;/td&gt;&lt;td&gt;一级缓存作用域&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;jdbcTypeForNull&lt;/code&gt;&lt;/td&gt;&lt;td&gt;JDBC 类型&lt;/td&gt;&lt;td&gt;&lt;code&gt;OTHER&lt;/code&gt;&lt;/td&gt;&lt;td&gt;为 &lt;code&gt;null&lt;/code&gt; 参数指定 JDBC 类型&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;logImpl&lt;/code&gt;&lt;/td&gt;&lt;td&gt;日志实现类&lt;/td&gt;&lt;td&gt;自动检测&lt;/td&gt;&lt;td&gt;指定 MyBatis 使用的日志实现&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;autoMappingBehavior&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;NONE&lt;/code&gt;、&lt;code&gt;PARTIAL&lt;/code&gt;、&lt;code&gt;FULL&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;PARTIAL&lt;/code&gt;&lt;/td&gt;&lt;td&gt;自动映射级别&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;三种数据源类型&lt;a href=&quot;#三种数据源类型&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;th&gt;适用场景&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;UNPOOLED&lt;/td&gt;&lt;td&gt;每次请求打开/关闭连接&lt;/td&gt;&lt;td&gt;简单应用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POOLED&lt;/td&gt;&lt;td&gt;连接池&lt;/td&gt;&lt;td&gt;大多数应用（推荐）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;JNDI&lt;/td&gt;&lt;td&gt;从 JNDI 获取数据源&lt;/td&gt;&lt;td&gt;应用服务器（Tomcat 等）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;两种事务管理器&lt;a href=&quot;#两种事务管理器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;type&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;th&gt;适用场景&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;JDBC&lt;/td&gt;&lt;td&gt;直接使用 JDBC 的 commit/rollback&lt;/td&gt;&lt;td&gt;独立应用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MANAGED&lt;/td&gt;&lt;td&gt;容器管理事务（不提交/回滚）&lt;/td&gt;&lt;td&gt;应用服务器、Spring&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;类型别名&lt;a href=&quot;#类型别名&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MyBatis 内置的常用别名：&lt;/p&gt;





































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;别名&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;Java &lt;strong&gt;类型&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;_int&lt;/td&gt;&lt;td&gt;int&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;int&lt;/td&gt;&lt;td&gt;Integer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;_long&lt;/td&gt;&lt;td&gt;long&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;long&lt;/td&gt;&lt;td&gt;Long&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;_boolean&lt;/td&gt;&lt;td&gt;boolean&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;boolean&lt;/td&gt;&lt;td&gt;Boolean&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;string&lt;/td&gt;&lt;td&gt;String&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;integer&lt;/td&gt;&lt;td&gt;Integer&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;date&lt;/td&gt;&lt;td&gt;Date&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;decimal&lt;/td&gt;&lt;td&gt;BigDecimal&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;object&lt;/td&gt;&lt;td&gt;Object&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;map&lt;/td&gt;&lt;td&gt;Map&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;hashmap&lt;/td&gt;&lt;td&gt;HashMap&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;list&lt;/td&gt;&lt;td&gt;List&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;arraylist&lt;/td&gt;&lt;td&gt;ArrayList&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;SqlSession 与映射器接口&lt;a href=&quot;#sqlsession-与映射器接口&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;SqlSession 生命周期&lt;a href=&quot;#sqlsession-生命周期&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; SqlSessionFactoryBuilder  →  一次创建后丢弃（方法局部变量）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         ▼&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; SqlSessionFactory          →  应用级别（单例，全局唯一）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         ▼&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; SqlSession                →  方法/请求级别（非线程安全）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         ▼&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Mapper 接口实例            →  SqlSession 级别&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;SqlSession 核心方法&lt;a href=&quot;#sqlsession-核心方法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; // 查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; T &lt;/span&gt;&lt;span&gt;selectOne&lt;/span&gt;&lt;span&gt;(String statement);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; T &lt;/span&gt;&lt;span&gt;selectOne&lt;/span&gt;&lt;span&gt;(String statement, Object parameter);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;E&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;E&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; selectList&lt;/span&gt;&lt;span&gt;(String statement);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;E&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;E&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; selectList&lt;/span&gt;&lt;span&gt;(String statement, Object parameter);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;E&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;E&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; selectList&lt;/span&gt;&lt;span&gt;(String statement, Object parameter, RowBounds rowBounds);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;K, V&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; Map&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;K, V&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; selectMap&lt;/span&gt;&lt;span&gt;(String statement, String mapKey);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;K, V&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; Map&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;K, V&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; selectMap&lt;/span&gt;&lt;span&gt;(String statement, Object parameter, String mapKey);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 游标查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; Cursor&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; selectCursor&lt;/span&gt;&lt;span&gt;(String statement);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 插入&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; insert&lt;/span&gt;&lt;span&gt;(String statement);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; insert&lt;/span&gt;&lt;span&gt;(String statement, Object parameter);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 更新&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; update&lt;/span&gt;&lt;span&gt;(String statement);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; update&lt;/span&gt;&lt;span&gt;(String statement, Object parameter);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 删除&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; delete&lt;/span&gt;&lt;span&gt;(String statement);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; delete&lt;/span&gt;&lt;span&gt;(String statement, Object parameter);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 事务&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; commit&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; commit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt; force);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; rollback&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; rollback&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt; force);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 批量&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; flushStatements&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 关闭&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 清除缓存&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;void&lt;/span&gt;&lt;span&gt; clearCache&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 获取配置&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Configuration &lt;/span&gt;&lt;span&gt;getConfiguration&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 获取映射器&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; T &lt;/span&gt;&lt;span&gt;getMapper&lt;/span&gt;&lt;span&gt;(Class&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; type);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 获取连接&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Connection &lt;/span&gt;&lt;span&gt;getConnection&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;两种使用方式&lt;a href=&quot;#两种使用方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;方式一：通过命名空间直接调用&lt;a href=&quot;#方式一通过命名空间直接调用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;SqlSession session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; MyBatisUtil.&lt;/span&gt;&lt;span&gt;getSqlSession&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; emps &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;selectList&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.EmpMapper.selectAll&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;session.&lt;/span&gt;&lt;span&gt;close&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;方式二：通过 Mapper 接口调用（推荐）&lt;a href=&quot;#方式二通过-mapper-接口调用推荐&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;SqlSession session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; MyBatisUtil.&lt;/span&gt;&lt;span&gt;getSqlSession&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpMapper mapper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;getMapper&lt;/span&gt;&lt;span&gt;(EmpMapper.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; emps &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;selectAll&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;session.&lt;/span&gt;&lt;span&gt;close&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;推荐方式二&lt;/strong&gt;：类型安全、IDE 提示、编译期检查。&lt;/p&gt;
&lt;h3&gt;三种执行器&lt;a href=&quot;#三种执行器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;执行器&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;th&gt;适用场景&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Simple&lt;/td&gt;&lt;td&gt;每次执行创建新 Statement&lt;/td&gt;&lt;td&gt;默认&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Reuse&lt;/td&gt;&lt;td&gt;复用 Statement&lt;/td&gt;&lt;td&gt;多次相同 SQL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Batch&lt;/td&gt;&lt;td&gt;批量执行&lt;/td&gt;&lt;td&gt;批量 INSERT/UPDATE&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;// 指定执行器&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;SqlSession session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sqlSessionFactory.&lt;/span&gt;&lt;span&gt;openSession&lt;/span&gt;&lt;span&gt;(ExecutorType.BATCH);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;事务管理&lt;a href=&quot;#事务管理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; // 手动提交（默认）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; SqlSession session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sqlSessionFactory.&lt;/span&gt;&lt;span&gt;openSession&lt;/span&gt;&lt;span&gt;();  &lt;/span&gt;&lt;span&gt;// autoCommit = false&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     EmpMapper mapper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;getMapper&lt;/span&gt;&lt;span&gt;(EmpMapper.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     mapper.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     session.&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt;();   &lt;/span&gt;&lt;span&gt;// 手动提交&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (Exception &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     session.&lt;/span&gt;&lt;span&gt;rollback&lt;/span&gt;&lt;span&gt;(); &lt;/span&gt;&lt;span&gt;// 回滚&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; } &lt;/span&gt;&lt;span&gt;finally&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    session.&lt;/span&gt;&lt;span&gt;close&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 自动提交&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;SqlSession session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sqlSessionFactory.&lt;/span&gt;&lt;span&gt;openSession&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;);  &lt;/span&gt;&lt;span&gt;// autoCommit = true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// try-with-resources（推荐）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; (SqlSession session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; sqlSessionFactory.&lt;/span&gt;&lt;span&gt;openSession&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    EmpMapper mapper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;getMapper&lt;/span&gt;&lt;span&gt;(EmpMapper.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    mapper.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    session.&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;映射器文件（Mapper XML）&lt;a href=&quot;#映射器文件mapper-xml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;完整结构&lt;a href=&quot;#完整结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;?&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span&gt; encoding&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!&lt;/span&gt;&lt;span&gt;DOCTYPE&lt;/span&gt;&lt;span&gt; mapper&lt;/span&gt;&lt;span&gt; PUBLIC &quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &quot;https://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- namespace 必须与 Mapper 接口全限定名一致 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt; namespace&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.EmpMapper&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- ============ 1. 缓存配置 ============ --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;cache&lt;/span&gt;&lt;span&gt;/&amp;gt;                    &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 开启二级缓存（默认） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;cache-ref&lt;/span&gt;&lt;span&gt; namespace&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.DeptMapper&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;  &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 引用其他命名空间的缓存 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- ============ 2. 结果映射 ============ --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empResultMap&quot;&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- ============ 3. SQL 片段 ============ --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;sql&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empColumns&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        emp_id, emp_name, email, salary, dept_id, hire_date, status&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;sql&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;sql&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empWhere&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName != null and empName != &apos;&apos;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                AND emp_name LIKE CONCAT(&apos;%&apos;, #{empName}, &apos;%&apos;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                AND dept_id = #{deptId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;sql&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- ============ 4. 查询 ============ --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectAll&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SELECT &amp;lt;&lt;/span&gt;&lt;span&gt;include&lt;/span&gt;&lt;span&gt; refid&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empColumns&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt; FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- ============ 5. 插入 ============ --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;insert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            useGeneratedKeys&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt; keyProperty&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        INSERT INTO emp (emp_name, email, salary, dept_id, hire_date, status)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        VALUES (#{empName}, #{email}, #{salary}, #{deptId}, #{hireDate}, #{status})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- ============ 6. 更新 ============ --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;update&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        UPDATE emp SET&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            emp_name = #{empName},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            salary = #{salary}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        WHERE emp_id = #{empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- ============ 7. 删除 ============ --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deleteById&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;int&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        DELETE FROM emp WHERE emp_id = #{empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;select 元素属性详解&lt;a href=&quot;#select-元素属性详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectEmp&quot;&lt;/span&gt;&lt;span&gt;              &amp;lt;!-- 必须与接口方法名一致 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     parameterType=&quot;map&quot;         &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 参数类型（可省略，自动推断） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     resultType=&quot;Emp&quot;            &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 返回类型 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     resultMap=&quot;empResultMap&quot;    &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 结果映射（与 resultType 二选一） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     flushCache=&quot;false&quot;          &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 是否清空缓存 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     useCache=&quot;true&quot;             &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 是否使用二级缓存 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     timeout=&quot;30&quot;                &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 超时秒数 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     fetchSize=&quot;100&quot;             &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 批量获取大小 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    statementType=&quot;PREPARED&quot;    &lt;/span&gt;&lt;span&gt;&amp;lt;!-- STATEMENT/PREPARED/CALLABLE --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    resultSetType=&quot;FORWARD_ONLY&quot; &lt;/span&gt;&lt;span&gt;&amp;lt;!-- FORWARD_ONLY/SCROLL_INSENSITIVE/SCROLL_SENSITIVE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    databaseId=&quot;mysql&quot;          &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 数据库厂商标识 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    resultOrdered=&quot;false&quot;       &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 嵌套结果是否按顺序 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    resultSets=&quot;emp,dept&quot;       &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 多结果集名 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT * FROM emp WHERE emp_id = #{empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;#{} 与 ${} 的区别&lt;a href=&quot;#-与--的区别&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;特性&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;#{}&lt;/th&gt;&lt;th&gt;${}&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;处理方式&lt;/td&gt;&lt;td&gt;预编译参数（PreparedStatement 的 ?）&lt;/td&gt;&lt;td&gt;字符串拼接&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;SQL 注入&lt;/td&gt;&lt;td&gt;✅ 防止&lt;/td&gt;&lt;td&gt;❌ 有风险&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;性能&lt;/td&gt;&lt;td&gt;可利用预编译缓存&lt;/td&gt;&lt;td&gt;每次都不同&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;使用场景&lt;/td&gt;&lt;td&gt;参数值&lt;/td&gt;&lt;td&gt;表名**/列名/ORDER BY**&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- #{}：安全，用于传值 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectById&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT * FROM emp WHERE emp_id = #{empId}  &lt;/span&gt;&lt;span&gt;&amp;lt;!-- → WHERE emp_id = ? --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- ${}：不安全，用于动态表名/列名 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByColumn&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT * FROM emp ORDER BY ${columnName} ${order}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- → SELECT * FROM emp ORDER BY emp_id DESC --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 必须对 ${} 的输入做校验 --&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;参数传递&lt;a href=&quot;#参数传递&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;单个参数&lt;a href=&quot;#单个参数&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;// 接口&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Emp &lt;/span&gt;&lt;span&gt;selectById&lt;/span&gt;&lt;span&gt;(Integer empId);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- XML：#{任意名} --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectById&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT * FROM emp WHERE emp_id = #{empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 也可写成 #{id} 或 #{任意名}，单参数不限制 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;多个参数（使用 @Param）&lt;a href=&quot;#多个参数使用-param&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;// 接口&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; selectByCondition&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;Param&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;empName&quot;&lt;/span&gt;&lt;span&gt;) String empName,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                             @&lt;/span&gt;&lt;span&gt;Param&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;deptId&quot;&lt;/span&gt;&lt;span&gt;) Integer deptId);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByCondition&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT * FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    WHERE emp_name LIKE CONCAT(&apos;%&apos;, #{empName}, &apos;%&apos;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      AND dept_id = #{deptId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;多个参数（使用 Map / 对象）&lt;a href=&quot;#多个参数使用-map--对象&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;// Map&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; selectByMap&lt;/span&gt;&lt;span&gt;(Map&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;String, Object&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; params);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 对象&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; selectByEmp&lt;/span&gt;&lt;span&gt;(Emp query);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- Map：#{key} --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByMap&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT * FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     WHERE emp_name = #{name} AND dept_id = #{deptId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- 对象：#{属性名} --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByEmp&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT * FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    WHERE emp_name = #{empName} AND dept_id = #{deptId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;参数为 List / Array&lt;a href=&quot;#参数为-list--array&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;1List&amp;lt;Emp&amp;gt; selectByIds(@Param(“ids”) List&amp;lt;Integer&amp;gt; ids);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByIds&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT * FROM emp WHERE emp_id IN&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt; collection&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;ids&quot;&lt;/span&gt;&lt;span&gt; item&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;id&quot;&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;(&quot;&lt;/span&gt;&lt;span&gt; separator&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;,&quot;&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;)&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        #{id}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;insert 元素详解&lt;a href=&quot;#insert-元素详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- 普通插入 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;insert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     INSERT INTO emp (emp_name, email, salary)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     VALUES (#{empName}, #{email}, #{salary})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- 主键回填（自增主键） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;insert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         useGeneratedKeys&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt; keyProperty&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; keyColumn&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    INSERT INTO emp (emp_name, email)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    VALUES (#{empName}, #{email})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 插入后 emp.getEmpId() 可获取生成的主键 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 主键回填（非自增主键，如 Oracle 序列） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;insert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;selectKey&lt;/span&gt;&lt;span&gt; keyProperty&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;int&quot;&lt;/span&gt;&lt;span&gt; order&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;BEFORE&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SELECT SEQ_EMP.NEXTVAL FROM DUAL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;selectKey&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    INSERT INTO emp (emp_id, emp_name)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    VALUES (#{empId}, #{empName})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- MySQL/PostgreSQL 使用 UUID --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;insert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;selectKey&lt;/span&gt;&lt;span&gt; keyProperty&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;string&quot;&lt;/span&gt;&lt;span&gt; order&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;BEFORE&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SELECT UUID()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;selectKey&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    INSERT INTO emp (emp_id, emp_name)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    VALUES (#{empId}, #{empName})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;code&gt;selectKey&lt;/code&gt; 属性&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;keyProperty&lt;/code&gt;&lt;/td&gt;&lt;td&gt;主键值要写入的 Java 属性&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;keyColumn&lt;/code&gt;&lt;/td&gt;&lt;td&gt;数据库中的主键列名，多列主键时可指定&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;resultType&lt;/code&gt;&lt;/td&gt;&lt;td&gt;主键值的 Java 类型&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;order&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;BEFORE&lt;/code&gt; 表示插入前查询主键，&lt;code&gt;AFTER&lt;/code&gt; 表示插入后查询主键&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;SQL 片段&lt;a href=&quot;#sql-片段&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;-- 定义 SQL 片段 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;sql&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empColumns&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    emp_id, emp_name, email, salary, dept_id, hire_date, &lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/sql&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;sql&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empColumnsWithAlias&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_id&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_name&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;email&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;salary&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;dept_id&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;hire_date&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;status&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/sql&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;-- 引用 SQL 片段 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectAll&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT&lt;/span&gt;&lt;span&gt; &amp;lt;include&lt;/span&gt;&lt;span&gt; refid&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empColumns&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;-- 带参数的 SQL 片段 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;sql&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;tableName&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ${prefix}_emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/sql&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectAll&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT&lt;/span&gt;&lt;span&gt; *&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; &amp;lt;include&lt;/span&gt;&lt;span&gt; refid&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;tableName&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property &lt;/span&gt;&lt;span&gt;name=&lt;/span&gt;&lt;span&gt;&quot;prefix&quot;&lt;/span&gt;&lt;span&gt; value=&lt;/span&gt;&lt;span&gt;&quot;t&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/include&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;ResultMap 详解&lt;a href=&quot;#resultmap-详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;为什么需要 ResultMap&lt;a href=&quot;#为什么需要-resultmap&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;当数据库列名与 Java 属性名不一致时，需要通过 ResultMap 进行映射：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;数据库列名: emp_id, emp_name, hire_date&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Java 属性名: empId, empName, hireDate&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 开启 mapUnderscoreToCamelCase 可自动映射&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;→ 但复杂映射（关联、集合、鉴别器）必须用 ResultMap&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;ResultMap 基本结构&lt;a href=&quot;#resultmap-基本结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;resultMap id=&quot;empResultMap&quot; type=&quot;Emp&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- id：主键映射（MyBatis 用它判断对象唯一性） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;id property=&quot;empId&quot; column=&quot;emp_id&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- result：普通字段映射 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;result property=&quot;empName&quot; column=&quot;emp_name&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;result property=&quot;email&quot; column=&quot;email&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;result property=&quot;salary&quot; column=&quot;salary&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;result property=&quot;hireDate&quot; column=&quot;hire_date&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/resultMap&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;constructor 构造器映射&lt;a href=&quot;#constructor-构造器映射&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; // 实体类有带参构造器&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; Integer empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;empId&lt;/span&gt;&lt;span&gt;, String &lt;/span&gt;&lt;span&gt;empName&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         this&lt;/span&gt;&lt;span&gt;.empId &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         this&lt;/span&gt;&lt;span&gt;.empName &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;resultMap id=&quot;empResultMap&quot; type=&quot;Emp&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;constructor&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;idArg javaType=&quot;int&quot; column=&quot;emp_id&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;arg javaType=&quot;string&quot; column=&quot;emp_name&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/constructor&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/resultMap&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;autoMapping 自动映射&lt;a href=&quot;#automapping-自动映射&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- 全局设置 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;settings&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- NONE: 禁用自动映射 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- PARTIAL(默认): 自动映射非嵌套结果 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- FULL: 自动映射所有（含嵌套） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;setting name=&quot;autoMappingBehavior&quot; value=&quot;PARTIAL&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/settings&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- ResultMap 级别 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;resultMap id=&quot;empResultMap&quot; type=&quot;Emp&quot; autoMapping=&quot;true&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;id property=&quot;empId&quot; column=&quot;emp_id&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;result property=&quot;empName&quot; column=&quot;emp_name&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 其他字段自动映射 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/resultMap&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;ResultMap 继承&lt;a href=&quot;#resultmap-继承&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- 基础 ResultMap --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;resultMap id=&quot;baseResultMap&quot; type=&quot;Emp&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;id property=&quot;empId&quot; column=&quot;emp_id&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;result property=&quot;empName&quot; column=&quot;emp_name&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;result property=&quot;email&quot; column=&quot;email&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;result property=&quot;salary&quot; column=&quot;salary&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/resultMap&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- 继承并扩展 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;resultMap id=&quot;empWithDeptResultMap&quot; type=&quot;Emp&quot; extends=&quot;baseResultMap&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;association property=&quot;dept&quot; javaType=&quot;Dept&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;id property=&quot;deptId&quot; column=&quot;d_dept_id&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;result property=&quot;deptName&quot; column=&quot;dept_name&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/association&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/resultMap&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;鉴别器（Discriminator）&lt;a href=&quot;#鉴别器discriminator&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;根据某列的值决定使用不同的 ResultMap：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;resultMap id=&quot;employeeResultMap&quot; type=&quot;Emp&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;id property=&quot;empId&quot; column=&quot;emp_id&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;result property=&quot;empName&quot; column=&quot;emp_name&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 鉴别器：根据 status 的值决定映射方式 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;discriminator javaType=&quot;int&quot; column=&quot;status&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;!-- status = 1：在职员工，映射部门 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;case value=&quot;1&quot; resultType=&quot;Emp&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;association property=&quot;dept&quot; javaType=&quot;Dept&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;id property=&quot;deptId&quot; column=&quot;dept_id&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;result property=&quot;deptName&quot; column=&quot;dept_name&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/association&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/case&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- status = 0：离职员工，映射离职信息 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;case value=&quot;0&quot; resultType=&quot;Emp&quot; resultMap=&quot;resignedEmpResultMap&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/discriminator&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/resultMap&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;动态 SQL&lt;a href=&quot;#动态-sql&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;动态 SQL 元素总览&lt;a href=&quot;#动态-sql-元素总览&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;元素&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;th&gt;类似于&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;if&amp;gt;&lt;/td&gt;&lt;td&gt;条件判断&lt;/td&gt;&lt;td&gt;if&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;choose&amp;gt;/&amp;lt;when&amp;gt;/&amp;lt;otherwise&amp;gt;&lt;/td&gt;&lt;td&gt;多条件选择&lt;/td&gt;&lt;td&gt;switch/case/default&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;where&amp;gt;&lt;/td&gt;&lt;td&gt;智能 WHERE 子句&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;set&amp;gt;&lt;/td&gt;&lt;td&gt;智能 SET 子句&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;trim&amp;gt;&lt;/td&gt;&lt;td&gt;自定义前缀/后缀裁剪&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;foreach&amp;gt;&lt;/td&gt;&lt;td&gt;遍历集合&lt;/td&gt;&lt;td&gt;for&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;bind&amp;gt;&lt;/td&gt;&lt;td&gt;绑定变量&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;sql&amp;gt;/&amp;lt;include&amp;gt;&lt;/td&gt;&lt;td&gt;SQL 片段复用&lt;/td&gt;&lt;td&gt;—&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;if 元素&lt;a href=&quot;#if-元素&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByCondition&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT * FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     WHERE 1=1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName != null and empName != &apos;&apos;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         AND emp_name LIKE CONCAT(&apos;%&apos;, #{empName}, &apos;%&apos;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         AND dept_id = #{deptId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;minSalary != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        AND salary &lt;/span&gt;&lt;span&gt;&amp;amp;gt;&lt;/span&gt;&lt;span&gt;= #{minSalary}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;maxSalary != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        AND salary &lt;/span&gt;&lt;span&gt;&amp;amp;lt;&lt;/span&gt;&lt;span&gt;= #{maxSalary}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;status != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        AND status = #{status}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：XML 中 &amp;lt; 和 &amp;gt; 需要转义为 &amp;amp;lt; 和 &amp;amp;gt;，或使用 &amp;lt;![CDATA[…]]&amp;gt; 包裹。&lt;/p&gt;
&lt;h3&gt;where 元素&lt;a href=&quot;#where-元素&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&amp;lt;where&amp;gt; 会自动处理：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;去掉首个 AND 或 OR&lt;/li&gt;
&lt;li&gt;如果没有任何条件，则不加 WHERE&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByCondition&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT * FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName != null and empName != &apos;&apos;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             AND emp_name LIKE CONCAT(&apos;%&apos;, #{empName}, &apos;%&apos;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             AND dept_id = #{deptId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;minSalary != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            AND salary &lt;/span&gt;&lt;span&gt;&amp;amp;gt;&lt;/span&gt;&lt;span&gt;= #{minSalary}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;choose / when / otherwise&lt;a href=&quot;#choose--when--otherwise&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByChoice&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT * FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;choose&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;when&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName != null and empName != &apos;&apos;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 emp_name = #{empName}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;/&lt;/span&gt;&lt;span&gt;when&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;when&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email != null and email != &apos;&apos;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 email = #{email}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;when&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;otherwise&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                status = 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;otherwise&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;choose&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;set 元素&lt;a href=&quot;#set-元素&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&amp;lt;set&amp;gt; 会自动处理：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;去掉末尾多余的逗号&lt;/li&gt;
&lt;li&gt;如果没有任何条件，则不加 SET（会报错）&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;updateSelective&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     UPDATE emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;emp_name = #{empName},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;email = #{email},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;salary = #{salary},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;dept_id = #{deptId},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;status != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;status = #{status},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    WHERE emp_id = #{empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;trim 元素&lt;a href=&quot;#trim-元素&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;&amp;lt;trim&amp;gt;&lt;/code&gt; 是 &lt;code&gt;&amp;lt;where&amp;gt;&lt;/code&gt; 和 &lt;code&gt;&amp;lt;set&amp;gt;&lt;/code&gt; 等元素的基础能力之一，可以自定义前缀、后缀以及需要移除的内容。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 等价于 &amp;lt;where&amp;gt; 的常见写法 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt; prefix&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;WHERE&quot;&lt;/span&gt;&lt;span&gt; prefixOverrides&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;AND |OR &quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 等价于 &amp;lt;set&amp;gt; 的常见写法 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt; prefix&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;SET&quot;&lt;/span&gt;&lt;span&gt; suffixOverrides&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;,&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;属性&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;prefix&lt;/code&gt;&lt;/td&gt;&lt;td&gt;在最终内容前添加前缀&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;suffix&lt;/code&gt;&lt;/td&gt;&lt;td&gt;在最终内容后添加后缀&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;prefixOverrides&lt;/code&gt;&lt;/td&gt;&lt;td&gt;移除内容开头匹配的字符串&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;suffixOverrides&lt;/code&gt;&lt;/td&gt;&lt;td&gt;移除内容末尾匹配的字符串&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;foreach 元素&lt;a href=&quot;#foreach-元素&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- IN 查询 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByIds&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT * FROM emp WHERE emp_id IN&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt; collection&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;ids&quot;&lt;/span&gt;&lt;span&gt; item&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;id&quot;&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;(&quot;&lt;/span&gt;&lt;span&gt; separator&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;,&quot;&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;)&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         #{id}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- 生成：SELECT * FROM emp WHERE emp_id IN (1, 2, 3) --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 批量插入 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;batchInsert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;list&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    INSERT INTO emp (emp_name, email, salary)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt; collection&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;list&quot;&lt;/span&gt;&lt;span&gt; item&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; separator&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;,&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        (#{emp.empName}, #{emp.email}, #{emp.salary})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 生成：INSERT INTO emp ... VALUES (&apos;张三&apos;,&apos;a@b.com&apos;,10000),(&apos;李四&apos;,&apos;c@d.com&apos;,12000) -&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     -&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!&lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt; 批量更新（CASE WHEN 方式） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;update id=&quot;batchUpdate&quot; parameterType=&quot;list&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    UPDATE emp SET&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    salary =&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;foreach collection=&quot;list&quot; item=&quot;emp&quot; open=&quot;CASE emp_id&quot; close=&quot;END&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        WHEN #{emp.empId} THEN #{emp.salary}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/foreach&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    WHERE emp_id IN&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;foreach collection=&quot;list&quot; item=&quot;emp&quot; open=&quot;(&quot; separator=&quot;,&quot; close=&quot;)&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        #{emp.empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/foreach&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/update&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- OR 条件 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;select id=&quot;selectByNames&quot; resultType=&quot;Emp&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT * FROM emp WHERE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;foreach collection=&quot;names&quot; item=&quot;name&quot; separator=&quot; OR &quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        emp_name = #{name}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/foreach&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;属性&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;collection&lt;/code&gt;&lt;/td&gt;&lt;td&gt;要遍历的集合名称。单个 &lt;code&gt;List&lt;/code&gt; 参数通常为 &lt;code&gt;list&lt;/code&gt;，数组通常为 &lt;code&gt;array&lt;/code&gt;，也可以使用 &lt;code&gt;@Param&lt;/code&gt; 指定名称&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;item&lt;/code&gt;&lt;/td&gt;&lt;td&gt;当前元素的变量名&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;index&lt;/code&gt;&lt;/td&gt;&lt;td&gt;当前索引或 Map 的键&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;open&lt;/code&gt;&lt;/td&gt;&lt;td&gt;整段内容的起始字符串&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;close&lt;/code&gt;&lt;/td&gt;&lt;td&gt;整段内容的结束字符串&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;separator&lt;/code&gt;&lt;/td&gt;&lt;td&gt;相邻元素之间的分隔符&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;bind 元素&lt;a href=&quot;#bind-元素&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- 模糊查询拼接 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByName&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;bind&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;likeName&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&apos;%&apos; + empName + &apos;%&apos;&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT * FROM emp WHERE emp_name LIKE #{likeName}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- 绑定多个变量 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByCondition&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;bind&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;minSalaryValue&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;minSalary != null ? minSalary : 0&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;bind&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;maxSalaryValue&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;maxSalary != null ? maxSalary : 999999&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT * FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    WHERE salary BETWEEN #{minSalaryValue} AND #{maxSalaryValue}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;完整动态 SQL 示例&lt;a href=&quot;#完整动态-sql-示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByDynamicCondition&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;include&lt;/span&gt;&lt;span&gt; refid&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empColumns&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName != null and empName != &apos;&apos;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;bind&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;likeName&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&apos;%&apos; + empName + &apos;%&apos;&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            AND emp_name LIKE #{likeName}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email != null and email != &apos;&apos;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            AND email = #{email}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            AND dept_id = #{deptId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptIds != null and deptIds.size() &amp;gt; 0&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            AND dept_id IN&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt; collection&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptIds&quot;&lt;/span&gt;&lt;span&gt; item&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;did&quot;&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;(&quot;&lt;/span&gt;&lt;span&gt; separator&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;,&quot;&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;)&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                #{did}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;minSalary != null or maxSalary != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;choose&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;when&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;minSalary != null and maxSalary != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    AND salary BETWEEN #{minSalary} AND #{maxSalary}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;/&lt;/span&gt;&lt;span&gt;when&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;when&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;minSalary != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    AND salary &lt;/span&gt;&lt;span&gt;&amp;amp;gt;&lt;/span&gt;&lt;span&gt;= #{minSalary}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;/&lt;/span&gt;&lt;span&gt;when&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;otherwise&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    AND salary &lt;/span&gt;&lt;span&gt;&amp;amp;lt;&lt;/span&gt;&lt;span&gt;= #{maxSalary}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;/&lt;/span&gt;&lt;span&gt;otherwise&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;choose&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;status != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            AND status = #{status}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ORDER BY emp_id DESC&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;关联查询&lt;a href=&quot;#关联查询&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;一对一关联（association）&lt;a href=&quot;#一对一关联association&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;方式一：嵌套结果（join 查询，一次 SQL）&lt;a href=&quot;#方式一嵌套结果join-查询一次-sql&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Dept dept;  &lt;/span&gt;&lt;span&gt;// 关联的部门对象&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;resultMap id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empWithDeptResultMap&quot;&lt;/span&gt;&lt;span&gt; type=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;id property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;result property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;result property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;-- 一对一关联 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;association property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept&quot;&lt;/span&gt;&lt;span&gt; javaType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Dept&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;id property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;d_dept_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;result property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;d_dept_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;result property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;location&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;d_location&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;association&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectEmpWithDept&quot;&lt;/span&gt;&lt;span&gt; resultMap&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empWithDeptResultMap&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_id&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_name&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;email&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        d&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;dept_id&lt;/span&gt;&lt;span&gt;   AS&lt;/span&gt;&lt;span&gt; d_dept_id,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        d&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;dept_name&lt;/span&gt;&lt;span&gt; AS&lt;/span&gt;&lt;span&gt; d_dept_name,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        d&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;location&lt;/span&gt;&lt;span&gt;  AS&lt;/span&gt;&lt;span&gt; d_location&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    FROM&lt;/span&gt;&lt;span&gt; emp e&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    LEFT JOIN&lt;/span&gt;&lt;span&gt; dept d &lt;/span&gt;&lt;span&gt;ON&lt;/span&gt;&lt;span&gt; e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;dept_id&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; d&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;dept_id&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    WHERE&lt;/span&gt;&lt;span&gt; e&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;emp_id&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; #{empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;方式二：嵌套查询（分步查询，N+1 问题）&lt;a href=&quot;#方式二嵌套查询分步查询n1-问题&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empWithDeptStepResultMap&quot;&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- column: 传递给子查询的列名; select: 子查询的方法全限定名 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;association&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                  javaType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Dept&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                  column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept_id&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                  select&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.DeptMapper.selectById&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 fetchType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;lazy&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;  &lt;/span&gt;&lt;span&gt;&amp;lt;!-- lazy: 延迟加载; eager: 立即加载 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectEmpWithDeptStep&quot;&lt;/span&gt;&lt;span&gt; resultMap&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empWithDeptStepResultMap&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT * FROM emp WHERE emp_id = #{empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- DeptMapper.xml --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectById&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Dept&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT * FROM dept WHERE dept_id = #{deptId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行流程：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;先执行 SELECT * FROM emp WHERE emp_id = ?&lt;/li&gt;
&lt;li&gt;取出 dept_id，执行 SELECT * FROM dept WHERE dept_id = ?&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;方式三：嵌套查询传多个参数&lt;a href=&quot;#方式三嵌套查询传多个参数&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;association &lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             javaType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Dept&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;{deptId=dept_id, status=status}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             select&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.DeptMapper.selectByIdAndStatus&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             fetchType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;lazy&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;一对多关联（collection）&lt;a href=&quot;#一对多关联collection&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Dept&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer deptId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String deptName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; emps;  &lt;/span&gt;&lt;span&gt;// 关联的员工列表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;方式一：嵌套结果&lt;a href=&quot;#方式一嵌套结果&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptWithEmpsResultMap&quot;&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Dept&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;location&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;location&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 一对多关联 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;collection&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emps&quot;&lt;/span&gt;&lt;span&gt; ofType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;e_emp_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;e_emp_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;e_email&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;e_salary&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;collection&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectDeptWithEmps&quot;&lt;/span&gt;&lt;span&gt; resultMap&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptWithEmpsResultMap&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        d.dept_id,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        d.dept_name,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        d.location,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        e.emp_id   AS e_emp_id,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        e.emp_name AS e_emp_name,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        e.email    AS e_email,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        e.salary   AS e_salary&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    FROM dept d&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    LEFT JOIN emp e ON d.dept_id = e.dept_id&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    WHERE d.dept_id = #{deptId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;方式二：嵌套查询&lt;a href=&quot;#方式二嵌套查询&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptWithEmpsStepResultMap&quot;&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Dept&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;collection&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emps&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 ofType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept_id&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 select&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.EmpMapper.selectByDeptId&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 fetchType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;lazy&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectDeptWithEmpsStep&quot;&lt;/span&gt;&lt;span&gt; resultMap&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptWithEmpsStepResultMap&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT * FROM dept WHERE dept_id = #{deptId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;多对多关联&lt;a href=&quot;#多对多关联&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;Project&lt;/span&gt;&lt;span&gt;&amp;gt; projects;  &lt;/span&gt;&lt;span&gt;// 参与的项目&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empWithProjectsResultMap&quot;&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;collection&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;projects&quot;&lt;/span&gt;&lt;span&gt; ofType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Project&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;projectId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;p_project_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;projectName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;p_project_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;budget&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;p_budget&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;collection&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectEmpWithProjects&quot;&lt;/span&gt;&lt;span&gt; resultMap&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empWithProjectsResultMap&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        e.emp_id,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        e.emp_name,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        p.project_id   AS p_project_id,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        p.project_name AS p_project_name,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        p.budget       AS p_budget&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    FROM emp e&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    LEFT JOIN emp_project ep ON e.emp_id = ep.emp_id&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    LEFT JOIN project p ON ep.project_id = p.project_id&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    WHERE e.emp_id = #{empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;嵌套查询 vs 嵌套结果对比&lt;a href=&quot;#嵌套查询-vs-嵌套结果对比&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;特性&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;嵌套结果（&lt;strong&gt;join）&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;嵌套查询（分步**）**&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;SQL 次数&lt;/td&gt;&lt;td&gt;1 次（多表 JOIN**）**&lt;/td&gt;&lt;td&gt;N+1 次&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;性能&lt;/td&gt;&lt;td&gt;高（单次查询**）**&lt;/td&gt;&lt;td&gt;低（N+1 问题，但可延迟加载**）**&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;延迟加载&lt;/td&gt;&lt;td&gt;❌ 不支持&lt;/td&gt;&lt;td&gt;✅ 支持&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;SQL 复杂度&lt;/td&gt;&lt;td&gt;高（多表 JOIN**）**&lt;/td&gt;&lt;td&gt;低（简单查询**）**&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;数据量&lt;/td&gt;&lt;td&gt;大（笛卡尔积**）**&lt;/td&gt;&lt;td&gt;分步获取&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;推荐&lt;/td&gt;&lt;td&gt;关联数据少&lt;/td&gt;&lt;td&gt;关联数据多 + 延迟加载&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;延迟加载配置&lt;a href=&quot;#延迟加载配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- mybatis-config.xml --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;settings&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 全局开启延迟加载 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;setting name=&quot;lazyLoadingEnabled&quot; value=&quot;true&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- false: 按需加载（仅访问关联属性时才加载） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;setting name=&quot;aggressiveLazyLoading&quot; value=&quot;false&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 延迟加载触发方法 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;setting name=&quot;lazyLoadTriggerMethods&quot; value=&quot;equals,clone,hashCode,toString&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/settings&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 单个 association/collection 级别 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;association property=&quot;dept&quot; fetchType=&quot;lazy&quot; .../&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;collection property=&quot;emps&quot; fetchType=&quot;eager&quot; .../&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;缓存机制&lt;a href=&quot;#缓存机制&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;缓存体系&lt;a href=&quot;#缓存体系&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; ┌──────────────────────────────────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │             MyBatis 缓存体系                    │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │                                               │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  ┌─────────────┐    ┌─────────────────────┐  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  │  一级缓存     │    │    二级缓存           │  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  │  (SqlSession)│    │  (Mapper namespace)  │  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  │              │    │                      │  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  │  默认开启     │    │  需手动开启           │  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  │  Session级   │    │  跨SqlSession共享     │  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│  │  HashMap     │    │  可集成第三方          │  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│  └──────┬──────┘    └──────────┬───────────┘  │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│         │                      │              │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│         └──────────┬───────────┘              │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│                    ▼                          │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│              ┌───────────┐                    │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│              │   数据库    │                   │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│              └───────────┘                    │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└──────────────────────────────────────────────┘&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;查询顺序：二级缓存 → 一级缓存 → 数据库&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;一级缓存&lt;a href=&quot;#一级缓存&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;一级缓存是 &lt;strong&gt;SqlSession 级别&lt;/strong&gt;的缓存，默认开启，不可关闭。&lt;/p&gt;
&lt;h4&gt;工作原理&lt;a href=&quot;#工作原理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;同一次 SqlSession 中：&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;. 第一次查询 emp_id=1 → 查数据库 → 存入一级缓存&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;. 第二次查询 emp_id=1 → 直接从一级缓存获取&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;. 执行 insert/update/delete → 清空一级缓存&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;. session.commit() 或 session.close() → 一级缓存消失&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;一级缓存失效条件&lt;a href=&quot;#一级缓存失效条件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;条件&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;不同的 SqlSession&lt;/td&gt;&lt;td&gt;不同 session 不共享缓存&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;执行了 insert/update/delete&lt;/td&gt;&lt;td&gt;清空当前 session 的所有缓存&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;执行了 session.clearCache()&lt;/td&gt;&lt;td&gt;手动清空&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;执行了 session.commit()&lt;/td&gt;&lt;td&gt;清空缓存&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;执行了 flushCache=“true” 的查询&lt;/td&gt;&lt;td&gt;该查询清空缓存&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;一级缓存范围&lt;a href=&quot;#一级缓存范围&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 默认：SESSION（SqlSession 范围） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;setting name=&quot;localCacheScope&quot; value=&quot;SESSION&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- STATEMENT：每条语句执行后清空（相当于关闭一级缓存） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;setting name=&quot;localCacheScope&quot; value=&quot;STATEMENT&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;二级缓存&lt;a href=&quot;#二级缓存&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;二级缓存是 &lt;strong&gt;Mapper namespace 级别&lt;/strong&gt;的缓存，跨 SqlSession 共享。&lt;/p&gt;
&lt;h4&gt;开启方式&lt;a href=&quot;#开启方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 1. 全局开启（mybatis-config.xml） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;settings&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;cacheEnabled&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;settings&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 2. Mapper XML 中声明 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt; namespace&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.EmpMapper&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;cache&lt;/span&gt;&lt;span&gt;/&amp;gt;  &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 简单声明 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;cache 元素属性&lt;a href=&quot;#cache-元素属性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;cache&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.apache.ibatis.cache.impl.PerpetualCache&quot;&lt;/span&gt;&lt;span&gt;   &amp;lt;!-- 缓存实现类 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    eviction&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;LRU&quot;&lt;/span&gt;&lt;span&gt;       &amp;lt;!-- 淘汰策略 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    flushInterval&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;60000&quot;&lt;/span&gt;&lt;span&gt; &amp;lt;!-- 刷新间隔（毫秒） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    size&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1024&quot;&lt;/span&gt;&lt;span&gt;          &amp;lt;!-- 最大对象数 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    readOnly&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;     &amp;lt;!-- 是否只读 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;eviction 淘汰策略&lt;/strong&gt;说明&lt;/p&gt;
&lt;p&gt;LRU（默认）最近最少使用&lt;/p&gt;
&lt;p&gt;FIFO 先进先出&lt;/p&gt;
&lt;p&gt;SOFT 软引用（内存不足时回收）&lt;/p&gt;
&lt;p&gt;WEAK 弱引用（GC 时回收）&lt;/p&gt;

















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;readOnly&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;true&lt;/td&gt;&lt;td&gt;所有线程共享同一对象（性能高，不安全）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;false（默认）&lt;/td&gt;&lt;td&gt;每次返回缓存对象的副本（序列化，安全）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;二级缓存使用条件&lt;a href=&quot;#二级缓存使用条件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;实体类必须实现 Serializable 接口（readOnly=false 时）&lt;/li&gt;
&lt;li&gt;必须在 select 后 commit 或 close 才会写入二级缓存&lt;/li&gt;
&lt;li&gt;执行 insert/update/delete 会自动清空该 namespace 的二级缓存&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; testSecondLevelCache&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // Session 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    try&lt;/span&gt;&lt;span&gt; (SqlSession session1 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; factory.&lt;/span&gt;&lt;span&gt;openSession&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        EmpMapper mapper1 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session1.&lt;/span&gt;&lt;span&gt;getMapper&lt;/span&gt;&lt;span&gt;(EmpMapper.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Emp emp1 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper1.&lt;/span&gt;&lt;span&gt;selectById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         session1.&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt;();  &lt;/span&gt;&lt;span&gt;// 提交后写入二级缓存&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // Session 2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    try&lt;/span&gt;&lt;span&gt; (SqlSession session2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; factory.&lt;/span&gt;&lt;span&gt;openSession&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        EmpMapper mapper2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session2.&lt;/span&gt;&lt;span&gt;getMapper&lt;/span&gt;&lt;span&gt;(EmpMapper.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Emp emp2 &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper2.&lt;/span&gt;&lt;span&gt;selectById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);  &lt;/span&gt;&lt;span&gt;// 从二级缓存获取&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;select 的 useCache 和 flushCache&lt;a href=&quot;#select-的-usecache-和-flushcache&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- 该查询不使用二级缓存 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectCount&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;int&quot;&lt;/span&gt;&lt;span&gt; useCache&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT COUNT(*) FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- 该查询执行后清空缓存 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectFreshData&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt; flushCache&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT * FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- insert/update/delete 默认 flushCache=&quot;true&quot; --&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;cache-ref 引用其他命名空间缓存&lt;a href=&quot;#cache-ref-引用其他命名空间缓存&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 多个 Mapper 共享同一个缓存 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt; namespace&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.EmpMapper&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;cache&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt; namespace&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.EmpDeptMapper&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 引用 EmpMapper 的缓存 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;cache-ref&lt;/span&gt;&lt;span&gt; namespace&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.EmpMapper&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;集成第三方缓存（EhCache）&lt;a href=&quot;#集成第三方缓存ehcache&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 依赖 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis.caches&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-ehcache&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.2.1&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- Mapper XML --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;cache&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.caches.ehcache.EhcacheCache&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- 或带配置 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;cache&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.caches.ehcache.EhcacheCache&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;timeToIdleSeconds&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;3600&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;timeToLiveSeconds&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;7200&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;maxEntriesLocalHeap&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1000&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;maxEntriesLocalDisk&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;10000000&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;memoryStoreEvictionPolicy&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;LRU&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;cache&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;一级缓存 vs 二级缓存&lt;a href=&quot;#一级缓存-vs-二级缓存&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;特性&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;一级缓存&lt;/th&gt;&lt;th&gt;二级缓存&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;范围&lt;/td&gt;&lt;td&gt;SqlSession&lt;/td&gt;&lt;td&gt;Mapper namespace&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;共享&lt;/td&gt;&lt;td&gt;不共享&lt;/td&gt;&lt;td&gt;跨 SqlSession 共享&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;默认&lt;/td&gt;&lt;td&gt;开启&lt;/td&gt;&lt;td&gt;关闭&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;可关闭&lt;/td&gt;&lt;td&gt;可设置 STATEMENT&lt;/td&gt;&lt;td&gt;可设置 cacheEnabled=false&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;失效&lt;/td&gt;&lt;td&gt;增删改、commit、close&lt;/td&gt;&lt;td&gt;增删改同 namespace&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;存储&lt;/td&gt;&lt;td&gt;HashMap&lt;/td&gt;&lt;td&gt;可自定义（EhCache/Redis）&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;主键回填与批量操作&lt;a href=&quot;#主键回填与批量操作&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;主键回填&lt;a href=&quot;#主键回填&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;自增主键回填&lt;a href=&quot;#自增主键回填&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;insert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        useGeneratedKeys&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        keyProperty&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        keyColumn&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    INSERT INTO emp (emp_name, email, salary)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    VALUES (#{empName}, #{email}, #{salary})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Emp emp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;emp.&lt;/span&gt;&lt;span&gt;setEmpName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;张三&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mapper.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(emp.&lt;/span&gt;&lt;span&gt;getEmpId&lt;/span&gt;&lt;span&gt;());  &lt;/span&gt;&lt;span&gt;// 自动回填的主键&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;非自增主键（selectKey）&lt;a href=&quot;#非自增主键selectkey&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- Oracle 序列 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;insert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;selectKey&lt;/span&gt;&lt;span&gt; keyProperty&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;int&quot;&lt;/span&gt;&lt;span&gt; order&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;BEFORE&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         SELECT SEQ_EMP.NEXTVAL FROM DUAL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;selectKey&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     INSERT INTO emp (emp_id, emp_name) VALUES (#{empId}, #{empName})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- MySQL UUID --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;insert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;selectKey&lt;/span&gt;&lt;span&gt; keyProperty&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;string&quot;&lt;/span&gt;&lt;span&gt; order&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;BEFORE&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SELECT REPLACE(UUID(), &apos;-&apos;, &apos;&apos;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;selectKey&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    INSERT INTO emp (emp_id, emp_name) VALUES (#{empId}, #{empName})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;批量插入&lt;a href=&quot;#批量插入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;方式一：foreach 拼接 VALUES&lt;a href=&quot;#方式一foreach-拼接-values&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;batchInsert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;list&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    INSERT INTO emp (emp_name, email, salary, dept_id, hire_date, status)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt; collection&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;list&quot;&lt;/span&gt;&lt;span&gt; item&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; separator&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;,&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        (#{emp.empName}, #{emp.email}, #{emp.salary}, #{emp.deptId}, #{emp.hireDate}, #&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    {emp.status})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; emps &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; ArrayList&amp;lt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;emps.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(emp1);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;emps.&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(emp2);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mapper.&lt;/span&gt;&lt;span&gt;batchInsert&lt;/span&gt;&lt;span&gt;(emps);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;方式二：Batch 执行器&lt;a href=&quot;#方式二batch-执行器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; try&lt;/span&gt;&lt;span&gt; (SqlSession session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; factory.&lt;/span&gt;&lt;span&gt;openSession&lt;/span&gt;&lt;span&gt;(ExecutorType.BATCH, &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;)) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     EmpMapper mapper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;getMapper&lt;/span&gt;&lt;span&gt;(EmpMapper.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt;; i &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; 10000&lt;/span&gt;&lt;span&gt;; i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         Emp emp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         emp.&lt;/span&gt;&lt;span&gt;setEmpName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp_&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; i);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         mapper.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         if&lt;/span&gt;&lt;span&gt; (i &lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt; 1000&lt;/span&gt;&lt;span&gt; ==&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            session.&lt;/span&gt;&lt;span&gt;flushStatements&lt;/span&gt;&lt;span&gt;();  &lt;/span&gt;&lt;span&gt;// 每 1000 条执行一次&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    session.&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;方式三：ON DUPLICATE KEY UPDATE（MySQL 批量 upsert）&lt;a href=&quot;#方式三on-duplicate-key-updatemysql-批量-upsert&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;batchUpsert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;list&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     INSERT INTO emp (emp_id, emp_name, email, salary)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt; collection&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;list&quot;&lt;/span&gt;&lt;span&gt; item&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; separator&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;,&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         (#{emp.empId}, #{emp.empName}, #{emp.email}, #{emp.salary})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     ON DUPLICATE KEY UPDATE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         emp_name = VALUES(emp_name),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         email = VALUES(email),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        salary = VALUES(salary)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;批量更新&lt;a href=&quot;#批量更新&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;方式一：CASE WHEN&lt;a href=&quot;#方式一case-when&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;batchUpdate&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;list&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     UPDATE emp SET&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     salary =&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt; collection&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;list&quot;&lt;/span&gt;&lt;span&gt; item&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;CASE emp_id&quot;&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;END&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         WHEN #{emp.empId} THEN #{emp.salary}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     WHERE emp_id IN&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt; collection&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;list&quot;&lt;/span&gt;&lt;span&gt; item&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; open&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;(&quot;&lt;/span&gt;&lt;span&gt; separator&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;,&quot;&lt;/span&gt;&lt;span&gt; close&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;)&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         #{emp.empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;foreach&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;方式二：Batch 执行器&lt;a href=&quot;#方式二batch-执行器-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;try&lt;/span&gt;&lt;span&gt; (SqlSession session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; factory.&lt;/span&gt;&lt;span&gt;openSession&lt;/span&gt;&lt;span&gt;(ExecutorType.BATCH)) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    EmpMapper mapper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;getMapper&lt;/span&gt;&lt;span&gt;(EmpMapper.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    for&lt;/span&gt;&lt;span&gt; (Emp emp &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; empList) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        mapper.&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    session.&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;TypeHandler 类型处理器&lt;a href=&quot;#typehandler-类型处理器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;什么是 TypeHandler&lt;a href=&quot;#什么是-typehandler&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;TypeHandler 用于 Java 类型和 JDBC 类型之间的转换：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Java 类型  ←→  JDBC 类型&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;String    ←→  VARCHAR&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Integer   ←→  INT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Date      ←→  TIMESTAMP&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List      ←→  VARCHAR (自定义)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;内置 TypeHandler&lt;a href=&quot;#内置-typehandler&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MyBatis 内置了常用 Java 类型与 JDBC 类型之间的转换器。&lt;/p&gt;

































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;TypeHandler&lt;/th&gt;&lt;th&gt;Java 类型&lt;/th&gt;&lt;th&gt;JDBC 类型&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;BooleanTypeHandler&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Boolean&lt;/code&gt;、&lt;code&gt;boolean&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;BOOLEAN&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;IntegerTypeHandler&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Integer&lt;/code&gt;、&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;INTEGER&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;LongTypeHandler&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Long&lt;/code&gt;、&lt;code&gt;long&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;BIGINT&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;StringTypeHandler&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;String&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;VARCHAR&lt;/code&gt;、&lt;code&gt;CHAR&lt;/code&gt;、&lt;code&gt;LONGVARCHAR&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DateTypeHandler&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Date&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;BigDecimalTypeHandler&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;BigDecimal&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;DECIMAL&lt;/code&gt;、&lt;code&gt;NUMERIC&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ByteArrayTypeHandler&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;byte[]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;BLOB&lt;/code&gt;、&lt;code&gt;LONGVARBINARY&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;EnumTypeHandler&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Enum&lt;/code&gt;&lt;/td&gt;&lt;td&gt;通常为 &lt;code&gt;VARCHAR&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;EnumOrdinalTypeHandler&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Enum&lt;/code&gt; 的序号&lt;/td&gt;&lt;td&gt;&lt;code&gt;INTEGER&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;LocalDateTypeHandler&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;LocalDate&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;DATE&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;LocalDateTimeTypeHandler&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;LocalDateTime&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;自定义 TypeHandler&lt;a href=&quot;#自定义-typehandler&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;场景：将 List 存为 JSON 字符串&lt;a href=&quot;#场景将-list-存为-json-字符串&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.example.handler;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.type.BaseTypeHandler;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.type.JdbcType;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.type.MappedJdbcTypes;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.type.MappedTypes;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.sql.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.ArrayList;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.Arrays;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;MappedTypes&lt;/span&gt;&lt;span&gt;(List.class)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;MappedJdbcTypes&lt;/span&gt;&lt;span&gt;(JdbcType.VARCHAR)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; StringListTypeHandler&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; BaseTypeHandler&lt;/span&gt;&lt;span&gt;&amp;lt;List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 将 Java 类型 → JDBC 类型（存入数据库）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setNonNullParameter&lt;/span&gt;&lt;span&gt;(PreparedStatement &lt;/span&gt;&lt;span&gt;ps&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                    List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;parameter&lt;/span&gt;&lt;span&gt;, JdbcType &lt;/span&gt;&lt;span&gt;jdbcType&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; SQLException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // List → &quot;a,b,c&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String value &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; String.&lt;/span&gt;&lt;span&gt;join&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;,&quot;&lt;/span&gt;&lt;span&gt;, parameter);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        ps.&lt;/span&gt;&lt;span&gt;setString&lt;/span&gt;&lt;span&gt;(i, value);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 将 JDBC 类型 → Java 类型（从数据库读取）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;getNullableResult&lt;/span&gt;&lt;span&gt;(ResultSet &lt;/span&gt;&lt;span&gt;rs&lt;/span&gt;&lt;span&gt;, String &lt;/span&gt;&lt;span&gt;columnName&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; SQLException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String value &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; rs.&lt;/span&gt;&lt;span&gt;getString&lt;/span&gt;&lt;span&gt;(columnName);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; toList&lt;/span&gt;&lt;span&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;getNullableResult&lt;/span&gt;&lt;span&gt;(ResultSet &lt;/span&gt;&lt;span&gt;rs&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; columnIndex&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; SQLException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String value &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; rs.&lt;/span&gt;&lt;span&gt;getString&lt;/span&gt;&lt;span&gt;(columnIndex);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; toList&lt;/span&gt;&lt;span&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;getNullableResult&lt;/span&gt;&lt;span&gt;(CallableStatement &lt;/span&gt;&lt;span&gt;cs&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; columnIndex&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; SQLException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String value &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; cs.&lt;/span&gt;&lt;span&gt;getString&lt;/span&gt;&lt;span&gt;(columnIndex);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; toList&lt;/span&gt;&lt;span&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;toList&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (value &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; ||&lt;/span&gt;&lt;span&gt; value.&lt;/span&gt;&lt;span&gt;isEmpty&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; ArrayList&amp;lt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; Arrays.&lt;/span&gt;&lt;span&gt;asList&lt;/span&gt;&lt;span&gt;(value.&lt;/span&gt;&lt;span&gt;split&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;,&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;注册 TypeHandler&lt;a href=&quot;#注册-typehandler&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!--&lt;/span&gt;&lt;span&gt; mybatis&lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt;config.xml &lt;/span&gt;&lt;span&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;typeHandlers&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!--&lt;/span&gt;&lt;span&gt; 方式一：单个注册 &lt;/span&gt;&lt;span&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;typeHandler handler&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.handler.StringListTypeHandler&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!--&lt;/span&gt;&lt;span&gt; 方式二：包扫描 &lt;/span&gt;&lt;span&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;package&lt;/span&gt;&lt;span&gt; name=&quot;com.example.handler&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/type&lt;/span&gt;&lt;span&gt;H&lt;/span&gt;&lt;span&gt;andlers&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;使用 TypeHandler&lt;a href=&quot;#使用-typehandler&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- 在映射中指定 typeHandler --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empResultMap&quot;&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;tags&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;tags&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             typeHandler&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.handler.StringListTypeHandler&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- 在参数中指定 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;insert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    INSERT INTO emp (emp_name, tags)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    VALUES (#{empName}, #{tags, typeHandler=com.example.handler.StringListTypeHandler})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;枚举类型处理&lt;a href=&quot;#枚举类型处理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; enum&lt;/span&gt;&lt;span&gt; EmpStatus&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     ACTIVE&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;在职&quot;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     RESIGNED&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;离职&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt; code;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; String desc;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     EmpStatus&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; code&lt;/span&gt;&lt;span&gt;, String &lt;/span&gt;&lt;span&gt;desc&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         this&lt;/span&gt;&lt;span&gt;.code &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; code;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.desc &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; desc;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // getter...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 方式一：按名称存储（默认） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 存入 &quot;ACTIVE&quot;，读取时 Enum.valueOf(&quot;ACTIVE&quot;) --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;setting name=&quot;defaultEnumTypeHandler&quot; value=&quot;org.apache.ibatis.type.EnumTypeHandler&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 方式二：按序号存储 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 存入 0（ACTIVE 的序号） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;setting name=&quot;defaultEnumTypeHandler&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    value=&quot;org.apache.ibatis.type.EnumOrdinalTypeHandler&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;自定义枚举 TypeHandler（按 code 存储）&lt;a href=&quot;#自定义枚举-typehandler按-code-存储&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;MappedTypes&lt;/span&gt;&lt;span&gt;(EmpStatus.class)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; EmpStatusTypeHandler&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; BaseTypeHandler&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;EmpStatus&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setNonNullParameter&lt;/span&gt;&lt;span&gt;(PreparedStatement &lt;/span&gt;&lt;span&gt;ps&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                     EmpStatus &lt;/span&gt;&lt;span&gt;parameter&lt;/span&gt;&lt;span&gt;, JdbcType &lt;/span&gt;&lt;span&gt;jdbcType&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; SQLException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         ps.&lt;/span&gt;&lt;span&gt;setInt&lt;/span&gt;&lt;span&gt;(i, parameter.&lt;/span&gt;&lt;span&gt;getCode&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; EmpStatus &lt;/span&gt;&lt;span&gt;getNullableResult&lt;/span&gt;&lt;span&gt;(ResultSet &lt;/span&gt;&lt;span&gt;rs&lt;/span&gt;&lt;span&gt;, String &lt;/span&gt;&lt;span&gt;columnName&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; SQLException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        int&lt;/span&gt;&lt;span&gt; code &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; rs.&lt;/span&gt;&lt;span&gt;getInt&lt;/span&gt;&lt;span&gt;(columnName);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; EmpStatus.&lt;/span&gt;&lt;span&gt;fromCode&lt;/span&gt;&lt;span&gt;(code);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // ... 其他方法&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;ObjectFactory 对象工厂&lt;a href=&quot;#objectfactory-对象工厂&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;什么是 ObjectFactory&lt;a href=&quot;#什么是-objectfactory&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;ObjectFactory 负责创建结果对象的实例。默认实现是 DefaultObjectFactory。&lt;/p&gt;
&lt;h3&gt;自定义 ObjectFactory&lt;a href=&quot;#自定义-objectfactory&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.factory;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.reflection.factory.DefaultObjectFactory;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.Properties;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; CustomObjectFactory&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; DefaultObjectFactory&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; T &lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(Class&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        T object &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; super&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(type);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 可以在这里做初始化&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; object;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; T &lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(Class&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;, List&amp;lt;Class&amp;lt;&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span&gt;constructorArgTypes&lt;/span&gt;&lt;span&gt;, List&amp;lt;&lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     constructorArgs&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        T object &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; super&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(type, constructorArgTypes, constructorArgs);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 自定义初始化逻辑&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; object;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setProperties&lt;/span&gt;&lt;span&gt;(Properties &lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        super&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setProperties&lt;/span&gt;&lt;span&gt;(properties);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt; isCollection&lt;/span&gt;&lt;span&gt;(Class&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; super&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;isCollection&lt;/span&gt;&lt;span&gt;(type);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;objectFactory type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.factory.CustomObjectFactory&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;someProperty&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;100&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;objectFactory&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Plugin 插件机制（拦截器）&lt;a href=&quot;#plugin-插件机制拦截器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;插件原理&lt;a href=&quot;#插件原理&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MyBatis 允许通过插件（拦截器）拦截以下四大对象的方法调用：&lt;/p&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;对象&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;拦截的方法&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Executor&lt;/td&gt;&lt;td&gt;update, query, commit, rollback, createStatement 等&lt;/td&gt;&lt;td&gt;执行器&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ParameterHandler&lt;/td&gt;&lt;td&gt;setParameters&lt;/td&gt;&lt;td&gt;参数处理&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ResultSetHandler&lt;/td&gt;&lt;td&gt;handleResultSets&lt;/td&gt;&lt;td&gt;结果集处理&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;StatementHandler&lt;/td&gt;&lt;td&gt;prepare, parameterize, batch&lt;/td&gt;&lt;td&gt;SQL 语句处理&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;SqlSession.selectList()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    → Executor.query()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        → StatementHandler.prepare()      ← 可拦截（修改 SQL）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        → StatementHandler.parameterize()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            → ParameterHandler.setParameters()  ← 可拦截（修改参数）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        → StatementHandler.query()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            → ResultSetHandler.handleResultSets()  ← 可拦截（修改结果）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;编写自定义插件&lt;a href=&quot;#编写自定义插件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;h4&gt;分页拦截器示例&lt;a href=&quot;#分页拦截器示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.example.plugin;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.executor.Executor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.mapping.MappedStatement;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.plugin.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.session.ResultHandler;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.session.RowBounds;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.Properties;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Intercepts&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;Signature&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Executor.class,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    method&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;query&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    args&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; PagePlugin&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; Interceptor&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Properties properties;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Object &lt;/span&gt;&lt;span&gt;intercept&lt;/span&gt;&lt;span&gt;(Invocation &lt;/span&gt;&lt;span&gt;invocation&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Throwable {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 获取参数&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Object&lt;/span&gt;&lt;span&gt;[] args &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; invocation.&lt;/span&gt;&lt;span&gt;getArgs&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        MappedStatement ms &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (MappedStatement) args[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Object parameter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; args[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        RowBounds rowBounds &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (RowBounds) args[&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 执行原查询（获取总数）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // ... 分页逻辑&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 修改 RowBounds&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        args[&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;] &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; RowBounds&lt;/span&gt;&lt;span&gt;(offset, limit);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; invocation.&lt;/span&gt;&lt;span&gt;proceed&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Object &lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;(Object &lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; Plugin.&lt;/span&gt;&lt;span&gt;wrap&lt;/span&gt;&lt;span&gt;(target, &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setProperties&lt;/span&gt;&lt;span&gt;(Properties &lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.properties &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; properties;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!--&lt;/span&gt;&lt;span&gt; 注册插件 &lt;/span&gt;&lt;span&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;plugin interceptor&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.plugin.PagePlugin&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dialect&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mysql&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;SQL 审计拦截器示例&lt;a href=&quot;#sql-审计拦截器示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Intercepts&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Signature&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Executor.class, &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;update&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                args&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {MappedStatement.class, Object.class})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; SqlAuditPlugin&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; Interceptor&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; Object &lt;/span&gt;&lt;span&gt;intercept&lt;/span&gt;&lt;span&gt;(Invocation &lt;/span&gt;&lt;span&gt;invocation&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Throwable {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         MappedStatement ms &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (MappedStatement) invocation.&lt;/span&gt;&lt;span&gt;getArgs&lt;/span&gt;&lt;span&gt;()[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Object parameter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; invocation.&lt;/span&gt;&lt;span&gt;getArgs&lt;/span&gt;&lt;span&gt;()[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 获取 SQL ID&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String sqlId &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ms.&lt;/span&gt;&lt;span&gt;getId&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 获取 SQL 语句&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        BoundSql boundSql &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ms.&lt;/span&gt;&lt;span&gt;getBoundSql&lt;/span&gt;&lt;span&gt;(parameter);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String sql &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; boundSql.&lt;/span&gt;&lt;span&gt;getSql&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 记录审计日志&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        long&lt;/span&gt;&lt;span&gt; start &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; System.&lt;/span&gt;&lt;span&gt;currentTimeMillis&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Object result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; invocation.&lt;/span&gt;&lt;span&gt;proceed&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        long&lt;/span&gt;&lt;span&gt; elapsed &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; System.&lt;/span&gt;&lt;span&gt;currentTimeMillis&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; start;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;[SQL审计] &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; sqlId &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot; | 耗时: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; elapsed &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;ms&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;[SQL] &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; sql);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Object &lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;(Object &lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; Plugin.&lt;/span&gt;&lt;span&gt;wrap&lt;/span&gt;&lt;span&gt;(target, &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setProperties&lt;/span&gt;&lt;span&gt;(Properties &lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt;) {}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;分页&lt;a href=&quot;#分页&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;RowBounds 分页（内存分页）&lt;a href=&quot;#rowbounds-分页内存分页&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;// 内存分页（不推荐大数据量）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; offset &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; limit &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 10&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;RowBounds rowBounds &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; RowBounds&lt;/span&gt;&lt;span&gt;(offset, limit);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; emps &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;selectList&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.EmpMapper.selectAll&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    rowBounds);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;注意&lt;/strong&gt;：RowBounds 是内存分页，先查出全部数据再取子集，不推荐使用。&lt;/p&gt;
&lt;h3&gt;SQL 分页（推荐）&lt;a href=&quot;#sql-分页推荐&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;1List&amp;lt;Emp&amp;gt; selectByPage(@Param(“offset”) int offset, @Param(“limit”) int limit);&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByPage&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT * FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ORDER BY emp_id&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    LIMIT #{offset}, #{limit}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;PageHelper 分页插件（最常用）&lt;a href=&quot;#pagehelper-分页插件最常用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- 依赖 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.github.pagehelper&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;pagehelper&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;5.3.3&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- 或 MyBatis 专用版 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.github.pagehelper&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;pagehelper-spring-boot-starter&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;2.1.0&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- mybatis-config.xml 配置 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;plugins&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;plugin interceptor=&quot;com.github.pagehelper.PageInterceptor&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;!-- 数据库方言 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;property name=&quot;helperDialect&quot; value=&quot;mysql&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;!-- 分页合理化：页码 &amp;lt; 1 查第一页，&amp;gt; 最大页查最后一页 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;property name=&quot;reasonable&quot; value=&quot;true&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;!-- 支持通过 Mapper 接口参数传递分页参数 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;property name=&quot;supportMethodsArguments&quot; value=&quot;true&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 总数统计 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;property name=&quot;params&quot; value=&quot;count=countSql&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/plugin&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/plugins&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;使用 PageHelper&lt;a href=&quot;#使用-pagehelper&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; // 方式一：静态方法调用&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; PageHelper.&lt;/span&gt;&lt;span&gt;startPage&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;);  &lt;/span&gt;&lt;span&gt;// 第 1 页，每页 10 条&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; emps &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;selectAll&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; // PageHelper 会自动追加 LIMIT 0, 10&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; // 获取分页信息&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; PageInfo&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; pageInfo &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; PageInfo&amp;lt;&amp;gt;(emps);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;总记录数: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; pageInfo.&lt;/span&gt;&lt;span&gt;getTotal&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;总页数: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; pageInfo.&lt;/span&gt;&lt;span&gt;getPages&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;当前页: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; pageInfo.&lt;/span&gt;&lt;span&gt;getPageNum&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;每页大小: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; pageInfo.&lt;/span&gt;&lt;span&gt;getPageSize&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;是否有下一页: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; pageInfo.&lt;/span&gt;&lt;span&gt;isHasNextPage&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 方式二：通过参数传递&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; emps &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;selectByParams&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// PageHelper 自动处理&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 方式三：Lambda 方式&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;PageInfo&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; pageInfo &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; PageHelper.&lt;/span&gt;&lt;span&gt;startPage&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;doSelectPageInfo&lt;/span&gt;&lt;span&gt;(() &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;selectAll&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;PageInfo 属性&lt;a href=&quot;#pageinfo-属性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; PageInfo&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt; pageNum;        &lt;/span&gt;&lt;span&gt;// 当前页&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt; pageSize;       &lt;/span&gt;&lt;span&gt;// 每页大小&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; long&lt;/span&gt;&lt;span&gt; total;         &lt;/span&gt;&lt;span&gt;// 总记录数&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt; pages;          &lt;/span&gt;&lt;span&gt;// 总页数&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;&amp;gt; list;       &lt;/span&gt;&lt;span&gt;// 数据列表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt; prePage;        &lt;/span&gt;&lt;span&gt;// 上一页&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt; nextPage;       &lt;/span&gt;&lt;span&gt;// 下一页&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; isFirstPage;    &lt;/span&gt;&lt;span&gt;// 是否首页&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; isLastPage;     &lt;/span&gt;&lt;span&gt;// 是否末页&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; hasPreviousPage; &lt;/span&gt;&lt;span&gt;// 是否有上一页&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; hasNextPage;     &lt;/span&gt;&lt;span&gt;// 是否有下一页&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt; navigateFirstPage;   &lt;/span&gt;&lt;span&gt;// 导航首页&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt; navigateLastPage;    &lt;/span&gt;&lt;span&gt;// 导航末页&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; int&lt;/span&gt;&lt;span&gt;[] navigatepageNums;  &lt;/span&gt;&lt;span&gt;// 导航页码数组&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;注解开发&lt;a href=&quot;#注解开发&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;基本注解&lt;a href=&quot;#基本注解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public interface EmpMapper {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    //&lt;/span&gt;&lt;span&gt; 查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @Select(&lt;/span&gt;&lt;span&gt;&quot;SELECT * FROM emp WHERE emp_id = #{empId}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     Emp selectById(&lt;/span&gt;&lt;span&gt;Integer&lt;/span&gt;&lt;span&gt; empId);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     //&lt;/span&gt;&lt;span&gt; 查询列表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @Select(&lt;/span&gt;&lt;span&gt;&quot;SELECT * FROM emp WHERE dept_id = #{deptId}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; selectByDeptId(&lt;/span&gt;&lt;span&gt;Integer&lt;/span&gt;&lt;span&gt; deptId);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    //&lt;/span&gt;&lt;span&gt; 插入（主键回填）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @Insert(&lt;/span&gt;&lt;span&gt;&quot;INSERT INTO emp (emp_name, email, salary) VALUES (#{empName}, #{email}, #&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     {salary})&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @Options(useGeneratedKeys &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; true, keyProperty &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;empId&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; insert&lt;/span&gt;&lt;span&gt;(Emp emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    //&lt;/span&gt;&lt;span&gt; 更新&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @Update(&lt;/span&gt;&lt;span&gt;&quot;UPDATE emp SET emp_name = #{empName}, salary = #{salary} WHERE emp_id = #&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     {empId}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; update&lt;/span&gt;&lt;span&gt;(Emp emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    //&lt;/span&gt;&lt;span&gt; 删除&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @Delete(&lt;/span&gt;&lt;span&gt;&quot;DELETE FROM emp WHERE emp_id = #{empId}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; deleteById(&lt;/span&gt;&lt;span&gt;Integer&lt;/span&gt;&lt;span&gt; empId);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    //&lt;/span&gt;&lt;span&gt; 查询数量&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @Select(&lt;/span&gt;&lt;span&gt;&quot;SELECT COUNT(*) FROM emp&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; selectCount();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Results 和 Result 注解&lt;a href=&quot;#results-和-result-注解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; @Results({&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @Result(property &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;empId&quot;&lt;/span&gt;&lt;span&gt;, column &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;emp_id&quot;&lt;/span&gt;&lt;span&gt;, id &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; true),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @Result(property &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;empName&quot;&lt;/span&gt;&lt;span&gt;, column &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;emp_name&quot;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @Result(property &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;hireDate&quot;&lt;/span&gt;&lt;span&gt;, column &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;hire_date&quot;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @Result(property &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;dept&quot;&lt;/span&gt;&lt;span&gt;, column &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;dept_id&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             one &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; @One(&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;com.example.mapper.DeptMapper.selectById&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        fetchType &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; FetchType&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;LAZY&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @Select(&lt;/span&gt;&lt;span&gt;&quot;SELECT * FROM emp WHERE emp_id = #{empId}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Emp selectByIdWithDept(&lt;/span&gt;&lt;span&gt;Integer&lt;/span&gt;&lt;span&gt; empId);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;一对多注解&lt;a href=&quot;#一对多注解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@Results({&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @Result(property &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;deptId&quot;&lt;/span&gt;&lt;span&gt;, column &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;dept_id&quot;&lt;/span&gt;&lt;span&gt;, id &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; true),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @Result(property &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;deptName&quot;&lt;/span&gt;&lt;span&gt;, column &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;dept_name&quot;&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @Result(property &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;emps&quot;&lt;/span&gt;&lt;span&gt;, column &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;dept_id&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            many &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; @Many(&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;com.example.mapper.EmpMapper.selectByDeptId&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                         fetchType &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; FetchType&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;LAZY&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@Select(&lt;/span&gt;&lt;span&gt;&quot;SELECT * FROM dept WHERE dept_id = #{deptId}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Dept selectDeptWithEmps(&lt;/span&gt;&lt;span&gt;Integer&lt;/span&gt;&lt;span&gt; deptId);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;动态 SQL 注解（@SelectProvider 等）&lt;a href=&quot;#动态-sql-注解selectprovider-等&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; // Provider 方式&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; EmpSqlProvider&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;selectByCondition&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;final&lt;/span&gt;&lt;span&gt; Emp &lt;/span&gt;&lt;span&gt;emp&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; SQL&lt;/span&gt;&lt;span&gt;() {{&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             SELECT&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;*&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             FROM&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             if&lt;/span&gt;&lt;span&gt; (emp.&lt;/span&gt;&lt;span&gt;getEmpName&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 WHERE&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp_name LIKE CONCAT(&apos;%&apos;, #{empName}, &apos;%&apos;)&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            if&lt;/span&gt;&lt;span&gt; (emp.&lt;/span&gt;&lt;span&gt;getDeptId&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                WHERE&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;dept_id = #{deptId}&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            if&lt;/span&gt;&lt;span&gt; (emp.&lt;/span&gt;&lt;span&gt;getStatus&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                WHERE&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;status = #{status}&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            ORDER_BY&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp_id DESC&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }}.&lt;/span&gt;&lt;span&gt;toString&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 接口&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; EmpMapper&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;SelectProvider&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; EmpSqlProvider.class, &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;selectByCondition&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;selectByCondition&lt;/span&gt;&lt;span&gt;(Emp &lt;/span&gt;&lt;span&gt;emp&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;InsertProvider&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; EmpSqlProvider.class, &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;insert&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; insert&lt;/span&gt;&lt;span&gt;(Emp &lt;/span&gt;&lt;span&gt;emp&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;UpdateProvider&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; EmpSqlProvider.class, &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;update&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; update&lt;/span&gt;&lt;span&gt;(Emp &lt;/span&gt;&lt;span&gt;emp&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;DeleteProvider&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; EmpSqlProvider.class, &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;delete&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; delete&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;empId&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;注解与 XML 对比&lt;a href=&quot;#注解与-xml-对比&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;特性&lt;/th&gt;&lt;th&gt;XML 映射&lt;/th&gt;&lt;th&gt;注解映射&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;SQL 复杂度&lt;/td&gt;&lt;td&gt;适合复杂 SQL 和大型动态 SQL&lt;/td&gt;&lt;td&gt;适合简单 SQL，复杂场景通常需要 Provider&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;动态 SQL&lt;/td&gt;&lt;td&gt;功能完整、可读性较好&lt;/td&gt;&lt;td&gt;能实现，但代码通常更分散&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;可读性&lt;/td&gt;&lt;td&gt;SQL 与 Java 代码分离&lt;/td&gt;&lt;td&gt;简单语句直观&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;维护性&lt;/td&gt;&lt;td&gt;复杂查询更易集中维护&lt;/td&gt;&lt;td&gt;简单 CRUD 维护成本低&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;推荐场景&lt;/td&gt;&lt;td&gt;复杂查询、多人协作项目&lt;/td&gt;&lt;td&gt;简单 CRUD、少量固定 SQL&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Spring 集成&lt;a href=&quot;#spring-集成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;依赖&lt;a href=&quot;#依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-spring&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.0.3&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-jdbc&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;6.1.5&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-context&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;6.1.5&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 数据源 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.zaxxer&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;HikariCP&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;5.1.0&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Spring 配置（XML 方式）&lt;a href=&quot;#spring-配置xml-方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- 数据源 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.zaxxer.hikari.HikariDataSource&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;driverClassName&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.mysql.cj.jdbc.Driver&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jdbcUrl&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jdbc:mysql://localhost:3306/mydb&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;username&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;root&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;password&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;root123&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;maximumPoolSize&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;10&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;connectionTimeout&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;30000&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- SqlSessionFactory --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;sqlSessionFactory&quot;&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.spring.SqlSessionFactoryBean&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt; ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;configLocation&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;classpath:mybatis-config.xml&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mapperLocations&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;classpath:mapper/*.xml&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;typeAliasesPackage&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- Mapper 扫描 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.spring.mapper.MapperScannerConfigurer&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;basePackage&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;sqlSessionFactoryBeanName&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;sqlSessionFactory&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 事务管理 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;transactionManager&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     class&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.springframework.jdbc.datasource.DataSourceTransactionManager&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt; ref&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dataSource&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;bean&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;tx:annotation-driven&lt;/span&gt;&lt;span&gt; transaction-manager&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;transactionManager&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Spring 配置（Java 配置方式）&lt;a href=&quot;#spring-配置java-配置方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;MapperScan&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;EnableTransactionManagement&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MyBatisConfig&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; DataSource &lt;/span&gt;&lt;span&gt;dataSource&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         HikariConfig config &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; HikariConfig&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         config.&lt;/span&gt;&lt;span&gt;setDriverClassName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.mysql.cj.jdbc.Driver&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        config.&lt;/span&gt;&lt;span&gt;setJdbcUrl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;jdbc:mysql://localhost:3306/mydb&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        config.&lt;/span&gt;&lt;span&gt;setUsername&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;root&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        config.&lt;/span&gt;&lt;span&gt;setPassword&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;root123&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        config.&lt;/span&gt;&lt;span&gt;setMaximumPoolSize&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; HikariDataSource&lt;/span&gt;&lt;span&gt;(config);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; SqlSessionFactory &lt;/span&gt;&lt;span&gt;sqlSessionFactory&lt;/span&gt;&lt;span&gt;(DataSource &lt;/span&gt;&lt;span&gt;dataSource&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Exception&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SqlSessionFactoryBean factory &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; SqlSessionFactoryBean&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        factory.&lt;/span&gt;&lt;span&gt;setDataSource&lt;/span&gt;&lt;span&gt;(dataSource);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        factory.&lt;/span&gt;&lt;span&gt;setConfigLocation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; ClassPathResource&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;mybatis-config.xml&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        factory.&lt;/span&gt;&lt;span&gt;setMapperLocations&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; PathMatchingResourcePatternResolver&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;getResources&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;classpath:mapper/*.xml&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        factory.&lt;/span&gt;&lt;span&gt;setTypeAliasesPackage&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example.entity&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; factory.&lt;/span&gt;&lt;span&gt;getObject&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; DataSourceTransactionManager &lt;/span&gt;&lt;span&gt;transactionManager&lt;/span&gt;&lt;span&gt;(DataSource &lt;/span&gt;&lt;span&gt;dataSource&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; DataSourceTransactionManager&lt;/span&gt;&lt;span&gt;(dataSource);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Service 层使用&lt;a href=&quot;#service-层使用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; EmpServiceImpl&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; EmpService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Autowired&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; EmpMapper empMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; Emp &lt;/span&gt;&lt;span&gt;getEmpById&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;empId&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empMapper.&lt;/span&gt;&lt;span&gt;selectById&lt;/span&gt;&lt;span&gt;(empId);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; transferSalary&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;fromId&lt;/span&gt;&lt;span&gt;, Integer &lt;/span&gt;&lt;span&gt;toId&lt;/span&gt;&lt;span&gt;, BigDecimal &lt;/span&gt;&lt;span&gt;amount&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Emp from &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper.&lt;/span&gt;&lt;span&gt;selectById&lt;/span&gt;&lt;span&gt;(fromId);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Emp to &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper.&lt;/span&gt;&lt;span&gt;selectById&lt;/span&gt;&lt;span&gt;(toId);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        from.&lt;/span&gt;&lt;span&gt;setSalary&lt;/span&gt;&lt;span&gt;(from.&lt;/span&gt;&lt;span&gt;getSalary&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;subtract&lt;/span&gt;&lt;span&gt;(amount));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        to.&lt;/span&gt;&lt;span&gt;setSalary&lt;/span&gt;&lt;span&gt;(to.&lt;/span&gt;&lt;span&gt;getSalary&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;add&lt;/span&gt;&lt;span&gt;(amount));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        empMapper.&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;(from);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 模拟异常&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // int i = 1 / 0;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        empMapper.&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;(to);  &lt;/span&gt;&lt;span&gt;// 异常时自动回滚&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Spring Boot 集成&lt;a href=&quot;#spring-boot-集成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;依赖&lt;a href=&quot;#依赖-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis.spring.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-spring-boot-starter&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.0.3&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;application.yml&lt;a href=&quot;#applicationyml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;spring&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  datasource&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    url&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;jdbc:mysql://localhost:3306/mydb?useSSL=false&amp;amp;serverTimezone=Asia/Shanghai&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    username&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    password&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;root123&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    driver-class-name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;com.mysql.cj.jdbc.Driver&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    hikari&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      maximum-pool-size&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      minimum-idle&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      connection-timeout&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;30000&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mybatis&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  # 配置文件位置&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  config-location&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;classpath:mybatis-config.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  # Mapper XML 位置&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  mapper-locations&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;classpath:mapper/*.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  # 实体类包&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  type-aliases-package&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;com.example.entity&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  configuration&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    map-underscore-to-camel-case&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    cache-enabled&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    lazy-loading-enabled&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    default-executor-type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;reuse&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    log-impl&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;org.apache.ibatis.logging.slf4j.Slf4jImpl&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# PageHelper&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;pagehelper&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  helper-dialect&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;mysql&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  reasonable&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  support-methods-arguments&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;启动类&lt;a href=&quot;#启动类&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;SpringBootApplication&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;MapperScan&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Application&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SpringApplication.&lt;/span&gt;&lt;span&gt;run&lt;/span&gt;&lt;span&gt;(Application.class, args);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;完整项目结构&lt;a href=&quot;#完整项目结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;src/main/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── java/com/example/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── Application.java          ← 启动类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── config/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   └── MyBatisConfig.java    ← 可选：自定义配置&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   ├── controller/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   │   └── EmpController.java&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   ├── service/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   │   ├── EmpService.java&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   └── impl/EmpServiceImpl.java&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   ├── EmpMapper.java        ← Mapper 接口&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   └── DeptMapper.java&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── entity/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│       ├── Emp.java&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│       └── Dept.java&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└── resources/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ├── application.yml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ├── mybatis-config.xml        ← 可选&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ├── mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    │   ├── EmpMapper.xml         ← Mapper XML&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    │   └── DeptMapper.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    └── logback.xml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;MyBatis-Plus&lt;a href=&quot;#mybatis-plus&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;MyBatis-Plus 简介&lt;a href=&quot;#mybatis-plus-简介&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MyBatis-Plus（简称 MP）是一个 MyBatis 的增强工具，在 MyBatis 的基础上&lt;strong&gt;只做增强不做改变&lt;/strong&gt;，为简化开发、提高效率而生。&lt;/p&gt;
&lt;h3&gt;核心特性&lt;a href=&quot;#核心特性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; ┌─────────────────────────────────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │           MyBatis-Plus 核心特性               │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├──────────────┬─────────────────────────────┤&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  无侵入       │ 只做增强不做改变              │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  损耗小       │ 启动即注入基本 CURD           │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  强大的 CRUD  │ 内置通用 Mapper/Service      │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  Lambda 表达式│ 编译期检查字段名              │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  主键自动生成  │ 支持多种主键策略              │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  代码生成器    │ 快速生成代码                 │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│  分页插件      │ 内置分页                    │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│  逻辑删除      │ 内置逻辑删除                 │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│  乐观锁        │ 内置乐观锁                   │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│  自动填充      │ 自动填充创建/更新时间         │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└──────────────┴─────────────────────────────┘&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;依赖&lt;a href=&quot;#依赖-2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.baomidou&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-plus-spring-boot3-starter&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.5.5&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;实体类注解&lt;a href=&quot;#实体类注解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;TableName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt;)   &lt;/span&gt;&lt;span&gt;// 指定表名&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;TableId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; IdType.AUTO)   &lt;/span&gt;&lt;span&gt;// 主键策略&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; Integer empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt;)        &lt;/span&gt;&lt;span&gt;// 指定列名（驼峰自动映射时可省略）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;email&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String email;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;exist&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;)     &lt;/span&gt;&lt;span&gt;// 非数据库字段&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String tempField;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;fill&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; FieldFill.INSERT)  &lt;/span&gt;&lt;span&gt;// 插入时自动填充&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDateTime createTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;fill&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; FieldFill.INSERT_UPDATE)  &lt;/span&gt;&lt;span&gt;// 插入和更新时自动填充&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDateTime updateTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableLogic&lt;/span&gt;&lt;span&gt;                    // 逻辑删除字段&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;status&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer deleted;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Version&lt;/span&gt;&lt;span&gt;                       // 乐观锁版本号&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer version;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;code&gt;IdType&lt;/code&gt;&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;AUTO&lt;/code&gt;&lt;/td&gt;&lt;td&gt;使用数据库自增主键&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;NONE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;不指定主键策略，由全局配置或开发者决定&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;INPUT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;插入前由开发者手动设置主键&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ASSIGN_ID&lt;/code&gt;&lt;/td&gt;&lt;td&gt;使用默认标识符生成器分配 ID，通常为雪花算法生成的长整型值&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ASSIGN_UUID&lt;/code&gt;&lt;/td&gt;&lt;td&gt;分配不带连字符的 UUID 字符串&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;BaseMapper 通用 CRUD&lt;a href=&quot;#basemapper-通用-crud&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; EmpMapper&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; BaseMapper&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 自动拥有以下方法，无需编写 XML&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 使用&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpMapper mapper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ...;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; // 插入&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 根据 ID 删除&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mapper.&lt;/span&gt;&lt;span&gt;deleteById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 根据 ID 更新&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mapper.&lt;/span&gt;&lt;span&gt;updateById&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 根据 ID 查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Emp emp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;selectById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 查询所有&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; list &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;selectList&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 条件查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; list &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;selectList&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    new&lt;/span&gt;&lt;span&gt; QueryWrapper&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;eq&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;dept_id&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;ge&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;salary&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;10000&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;like&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;张&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;orderByDesc&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;salary&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// Lambda 条件查询（推荐）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; list &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;selectList&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    new&lt;/span&gt;&lt;span&gt; LambdaQueryWrapper&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;eq&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getDeptId, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;ge&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getSalary, &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; BigDecimal&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;10000&quot;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;like&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getEmpName, &lt;/span&gt;&lt;span&gt;&quot;张&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;orderByDesc&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getSalary)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 查询数量&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Long count &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;selectCount&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 分页查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Page&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; page &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;selectPage&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    new&lt;/span&gt;&lt;span&gt; Page&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;),  &lt;/span&gt;&lt;span&gt;// 第1页，每页10条&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    new&lt;/span&gt;&lt;span&gt; LambdaQueryWrapper&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;().&lt;/span&gt;&lt;span&gt;eq&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getStatus, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; records &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; page.&lt;/span&gt;&lt;span&gt;getRecords&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;long&lt;/span&gt;&lt;span&gt; total &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; page.&lt;/span&gt;&lt;span&gt;getTotal&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;IService 通用 Service&lt;a href=&quot;#iservice-通用-service&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;// Service 接口&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; EmpService&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; IService&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// Service 实现&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; EmpServiceImpl&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; ServiceImpl&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;EmpMapper&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;implements&lt;/span&gt;&lt;span&gt; EmpService&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     {}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; // 使用&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Autowired&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; EmpService empService;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 保存&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;empService.&lt;/span&gt;&lt;span&gt;save&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 批量保存&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;empService.&lt;/span&gt;&lt;span&gt;saveBatch&lt;/span&gt;&lt;span&gt;(empList);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 批量保存（每100条提交一次）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;empService.&lt;/span&gt;&lt;span&gt;saveBatch&lt;/span&gt;&lt;span&gt;(empList, &lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 根据 ID 更新&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;empService.&lt;/span&gt;&lt;span&gt;updateById&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 保存或更新&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;empService.&lt;/span&gt;&lt;span&gt;saveOrUpdate&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 根据 ID 查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Emp emp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;getById&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 查询列表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; list &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 条件查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; list &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    new&lt;/span&gt;&lt;span&gt; LambdaQueryWrapper&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;().&lt;/span&gt;&lt;span&gt;eq&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getDeptId, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 分页&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Page&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; page &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    new&lt;/span&gt;&lt;span&gt; Page&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    new&lt;/span&gt;&lt;span&gt; LambdaQueryWrapper&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;().&lt;/span&gt;&lt;span&gt;eq&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getStatus, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 链式查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; list &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;lambdaQuery&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;eq&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getDeptId, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;ge&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getSalary, &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; BigDecimal&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;10000&quot;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 链式更新&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;empService.&lt;/span&gt;&lt;span&gt;lambdaUpdate&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;eq&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getDeptId, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getSalary, &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; BigDecimal&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;20000&quot;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 链式删除&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;empService.&lt;/span&gt;&lt;span&gt;lambdaUpdate&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;eq&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getStatus, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;remove&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;条件构造器常用方法&lt;a href=&quot;#条件构造器常用方法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

































































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;作用&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;eq(column, value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;等于&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ne(column, value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;不等于&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;gt(column, value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;大于&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ge(column, value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;大于等于&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;lt(column, value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;小于&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;le(column, value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;小于等于&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;like(column, value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;模糊匹配，值两侧添加通配符&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;likeLeft(column, value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;左模糊匹配&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;likeRight(column, value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;右模糊匹配&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;notLike(column, value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;非模糊匹配&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;in(column, list)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;集合包含&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;notIn(column, list)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;集合不包含&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;isNull(column)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;判断为空&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;isNotNull(column)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;判断非空&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;between(column, v1, v2)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;区间匹配&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;notBetween(column, v1, v2)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;非区间匹配&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;orderByDesc(column)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;降序排序&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;orderByAsc(column)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;升序排序&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;groupBy(column)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;分组&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;having(condition)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;添加 &lt;code&gt;HAVING&lt;/code&gt; 条件&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;last(sql)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;在语句末尾拼接 SQL，必须确保内容可信&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;select(columns...)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;指定查询列&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;分页插件配置&lt;a href=&quot;#分页插件配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MybatisPlusConfig&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; MybatisPlusInterceptor &lt;/span&gt;&lt;span&gt;mybatisPlusInterceptor&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         MybatisPlusInterceptor interceptor &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; MybatisPlusInterceptor&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         // 分页插件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         interceptor.&lt;/span&gt;&lt;span&gt;addInnerInterceptor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            new&lt;/span&gt;&lt;span&gt; PaginationInnerInterceptor&lt;/span&gt;&lt;span&gt;(DbType.MYSQL)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 乐观锁插件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        interceptor.&lt;/span&gt;&lt;span&gt;addInnerInterceptor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; OptimisticLockerInnerInterceptor&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; interceptor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;逻辑删除配置&lt;a href=&quot;#逻辑删除配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;mybatis-plus&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  global-config&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    db-config&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      logic-delete-field&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;span&gt;   # 逻辑删除字段&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      logic-delete-value&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;         # 已删除值&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      logic-not-delete-value&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;     # 未删除值&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;自动填充配置&lt;a href=&quot;#自动填充配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MyMetaObjectHandler&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; MetaObjectHandler&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; insertFill&lt;/span&gt;&lt;span&gt;(MetaObject &lt;/span&gt;&lt;span&gt;metaObject&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;strictInsertFill&lt;/span&gt;&lt;span&gt;(metaObject, &lt;/span&gt;&lt;span&gt;&quot;createTime&quot;&lt;/span&gt;&lt;span&gt;, LocalDateTime.class,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     LocalDateTime.&lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;strictInsertFill&lt;/span&gt;&lt;span&gt;(metaObject, &lt;/span&gt;&lt;span&gt;&quot;updateTime&quot;&lt;/span&gt;&lt;span&gt;, LocalDateTime.class,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     LocalDateTime.&lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; updateFill&lt;/span&gt;&lt;span&gt;(MetaObject &lt;/span&gt;&lt;span&gt;metaObject&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;strictUpdateFill&lt;/span&gt;&lt;span&gt;(metaObject, &lt;/span&gt;&lt;span&gt;&quot;updateTime&quot;&lt;/span&gt;&lt;span&gt;, LocalDateTime.class,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     LocalDateTime.&lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;代码生成器&lt;a href=&quot;#代码生成器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;MyBatis Generator (MBG)&lt;a href=&quot;#mybatis-generator-mbg&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- pom.xml --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis.generator&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-generator-maven-plugin&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.0.4&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;configurationFile&lt;/span&gt;&lt;span&gt;&amp;gt;src/main/resources/generatorConfig.xml&amp;lt;/&lt;/span&gt;&lt;span&gt;configurationFile&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;overwrite&lt;/span&gt;&lt;span&gt;&amp;gt;true&amp;lt;/&lt;/span&gt;&lt;span&gt;overwrite&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;verbose&lt;/span&gt;&lt;span&gt;&amp;gt;true&amp;lt;/&lt;/span&gt;&lt;span&gt;verbose&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;8.3.0&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- src/main/resources/generatorConfig.xml --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;?&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span&gt; encoding&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!&lt;/span&gt;&lt;span&gt;DOCTYPE&lt;/span&gt;&lt;span&gt; generatorConfiguration&lt;/span&gt;&lt;span&gt; PUBLIC&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &quot;-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &quot;https://mybatis.org/dtd/mybatis-generator-config_1_0.dtd&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;generatorConfiguration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;default&quot;&lt;/span&gt;&lt;span&gt; targetRuntime&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MyBatis3&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 不生成注释 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;suppressAllComments&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 数据库连接 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;jdbcConnection&lt;/span&gt;&lt;span&gt; driverClass&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.mysql.cj.jdbc.Driver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        connectionURL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jdbc:mysql://localhost:3306/mydb&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        userId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;root&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        password&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;root123&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 实体类生成路径 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;javaModelGenerator&lt;/span&gt;&lt;span&gt; targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                            targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/java&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;enableSubPackages&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;trimStrings&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;javaModelGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- Mapper XML 生成路径 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;sqlMapGenerator&lt;/span&gt;&lt;span&gt; targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                         targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/resources&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;enableSubPackages&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;sqlMapGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- Mapper 接口生成路径 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;javaClientGenerator&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;XMLMAPPER&quot;&lt;/span&gt;&lt;span&gt; targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                             targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/java&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;enableSubPackages&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;javaClientGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 要生成的表 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableCountByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableUpdateByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableDeleteByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableSelectByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               selectByExampleQueryId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept&quot;&lt;/span&gt;&lt;span&gt; domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Dept&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;generatorConfiguration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;1mvn mybatis-generator:generate&lt;/p&gt;
&lt;h3&gt;MyBatis-Plus 代码生成器&lt;a href=&quot;#mybatis-plus-代码生成器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; // 依赖&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; // mybatis-plus-generator 3.5.5&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; // velocity-engine-core 2.3&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; CodeGenerator&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         FastAutoGenerator.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 &quot;jdbc:mysql://localhost:3306/mydb&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 &quot;root&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;root123&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;globalConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            builder.&lt;/span&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;example&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                   .&lt;/span&gt;&lt;span&gt;outputDir&lt;/span&gt;&lt;span&gt;(System.&lt;/span&gt;&lt;span&gt;getProperty&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;user.dir&quot;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;/src/main/java&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                   .&lt;/span&gt;&lt;span&gt;commentDate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;yyyy-MM-dd&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;packageConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            builder.&lt;/span&gt;&lt;span&gt;parent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                   .&lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;entity&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                   .&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;mapper&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                   .&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;service&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                   .&lt;/span&gt;&lt;span&gt;serviceImpl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;service.impl&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                   .&lt;/span&gt;&lt;span&gt;controller&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;controller&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                   .&lt;/span&gt;&lt;span&gt;pathInfo&lt;/span&gt;&lt;span&gt;(Collections.&lt;/span&gt;&lt;span&gt;singletonMap&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       OutputFile.xml,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       System.&lt;/span&gt;&lt;span&gt;getProperty&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;user.dir&quot;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;/src/main/resources/mapper&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;strategyConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            builder.&lt;/span&gt;&lt;span&gt;addInclude&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;dept&quot;&lt;/span&gt;&lt;span&gt;)     &lt;/span&gt;&lt;span&gt;// 表名&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                   .&lt;/span&gt;&lt;span&gt;addTablePrefix&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;t_&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;sys_&quot;&lt;/span&gt;&lt;span&gt;)  &lt;/span&gt;&lt;span&gt;// 去除表前缀&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                   .&lt;/span&gt;&lt;span&gt;entityBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;enableLombok&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;enableTableFieldAnnotation&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;logicDeleteColumnName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;deleted&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;versionColumnName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;version&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                   .&lt;/span&gt;&lt;span&gt;mapperBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;enableMapperAnnotation&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                   .&lt;/span&gt;&lt;span&gt;serviceBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;formatServiceFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sService&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;formatServiceImplFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sServiceImpl&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;templateEngine&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; VelocityTemplateEngine&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;execute&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;性能优化&lt;a href=&quot;#性能优化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;SQL 优化&lt;a href=&quot;#sql-优化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;使用&lt;/strong&gt; #{} &lt;strong&gt;而非&lt;/strong&gt; ${}（防止 SQL 注入 + 利用预编译缓存）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;避免 SELECT *&lt;/strong&gt;，只查需要的列**&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;合理使用索引&lt;/strong&gt;（参考 MySQL 索引指南）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;避免 N+1 问题&lt;/strong&gt;（使用嵌套结果代替嵌套查询，或使用延迟加载）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;大批量操作使用 Batch 执行器&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;缓存优化&lt;a href=&quot;#缓存优化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;合理使用二级缓存&lt;/strong&gt;（读多写少的场景）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缓存粒度控制&lt;/strong&gt;（useCache / flushCache）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;集成 Redis 等分布式缓存&lt;/strong&gt;（替代本地缓存）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;延迟加载&lt;a href=&quot;#延迟加载&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 开启延迟加载，减少不必要的关联查询 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;setting name=&quot;lazyLoadingEnabled&quot; value=&quot;true&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;setting name=&quot;aggressiveLazyLoading&quot; value=&quot;false&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;连接池优化&lt;a href=&quot;#连接池优化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 使用 HikariCP 高性能连接池 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;dataSource type=&quot;POOLED&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;poolMaximumActiveConnections&quot; value=&quot;20&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;poolMaximumIdleConnections&quot; value=&quot;10&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;poolMaximumCheckoutTime&quot; value=&quot;20000&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;poolPingEnabled&quot; value=&quot;true&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;poolPingQuery&quot; value=&quot;SELECT 1&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/dataSource&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;批量操作优化&lt;a href=&quot;#批量操作优化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; // 使用 Batch 执行器&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; try&lt;/span&gt;&lt;span&gt; (SqlSession session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; factory.&lt;/span&gt;&lt;span&gt;openSession&lt;/span&gt;&lt;span&gt;(ExecutorType.BATCH)) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     EmpMapper mapper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;getMapper&lt;/span&gt;&lt;span&gt;(EmpMapper.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt;; i &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; 10000&lt;/span&gt;&lt;span&gt;; i&lt;/span&gt;&lt;span&gt;++&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         mapper.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         if&lt;/span&gt;&lt;span&gt; (i &lt;/span&gt;&lt;span&gt;%&lt;/span&gt;&lt;span&gt; 1000&lt;/span&gt;&lt;span&gt; ==&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             session.&lt;/span&gt;&lt;span&gt;flushStatements&lt;/span&gt;&lt;span&gt;();  &lt;/span&gt;&lt;span&gt;// 分批 flush&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    session.&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;fetchSize 优化&lt;a href=&quot;#fetchsize-优化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 大数据量查询时设置 fetchSize，减少网络交互 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectLargeData&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt; fetchSize&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1000&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT * FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;开启日志查看 SQL（开发环境）&lt;a href=&quot;#开启日志查看-sql开发环境&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;settings&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;setting name=&quot;logImpl&quot; value=&quot;SLF4J&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/settings&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;性能优化清单&lt;a href=&quot;#性能优化清单&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;优化项&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;th&gt;优先级&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;SQL 优化&lt;/td&gt;&lt;td&gt;合理使用索引、避免全表扫描&lt;/td&gt;&lt;td&gt;⭐⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;避免嵌套查询 N+1&lt;/td&gt;&lt;td&gt;使用 join 或延迟加载&lt;/td&gt;&lt;td&gt;⭐⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;批量操作&lt;/td&gt;&lt;td&gt;Batch 执行器&lt;/td&gt;&lt;td&gt;⭐⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;连接池调优&lt;/td&gt;&lt;td&gt;合理设置连接数&lt;/td&gt;&lt;td&gt;⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;二级缓存&lt;/td&gt;&lt;td&gt;读多写少场景&lt;/td&gt;&lt;td&gt;⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;延迟加载&lt;/td&gt;&lt;td&gt;减少不必要查询&lt;/td&gt;&lt;td&gt;⭐⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;fetchSize&lt;/td&gt;&lt;td&gt;大数据量查询&lt;/td&gt;&lt;td&gt;⭐&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;映射优化&lt;/td&gt;&lt;td&gt;只映射需要的字段&lt;/td&gt;&lt;td&gt;⭐&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;常见问题与排错&lt;a href=&quot;#常见问题与排错&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;BindingException&lt;/code&gt;：找不到映射语句&lt;a href=&quot;#bindingexception找不到映射语句&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;症状&lt;/strong&gt;：org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：Mapper 接口方法与 XML 中的 statement id 不匹配&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;检查 namespace 是否与接口全限定名一致&lt;/li&gt;
&lt;li&gt;检查 id 是否与方法名一致&lt;/li&gt;
&lt;li&gt;检查 XML 文件是否被正确加载（mapper-locations 配置）&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;参数绑定错误&lt;a href=&quot;#参数绑定错误&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;症状&lt;/strong&gt;：There is no getter for property named ‘xxx’&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;原因&lt;/strong&gt;：MyBatis 对单参数的处理规则&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;// 方式一：加 @Param&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; select&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;Param&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;empName&quot;&lt;/span&gt;&lt;span&gt;) String empName);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 方式二：用对象包装&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; select&lt;/span&gt;&lt;span&gt;(Emp query);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 方式三：用 Map&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; select&lt;/span&gt;&lt;span&gt;(Map&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;String, Object&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; params);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;中文乱码&lt;a href=&quot;#中文乱码&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;数据库 URL 加 characterEncoding=UTF-8&lt;/li&gt;
&lt;li&gt;XML 文件编码设为 UTF-8&lt;/li&gt;
&lt;li&gt;配置 &amp;lt;setting name=“logImpl” value=“SLF4J”/&amp;gt; 确保日志正确&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;一级缓存导致数据不一致&lt;a href=&quot;#一级缓存导致数据不一致&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;场景&lt;/strong&gt;：同一次 SqlSession 中，其他事务修改了数据，当前 session 仍返回旧数据&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 关闭一级缓存 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;setting&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;localCacheScope&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;STATEMENT&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 或在查询时刷新 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectFresh&quot;&lt;/span&gt;&lt;span&gt; flushCache&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;...&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;二级缓存序列化错误&lt;a href=&quot;#二级缓存序列化错误&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;症状&lt;/strong&gt;：NotSerializableException&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：实体类实现 Serializable 接口&lt;/p&gt;
&lt;h3&gt;嵌套查询 N+1 问题&lt;a href=&quot;#嵌套查询-n1-问题&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;使用嵌套结果（join）代替嵌套查询&lt;/li&gt;
&lt;li&gt;开启延迟加载&lt;/li&gt;
&lt;li&gt;使用 MyBatis-Plus 的批量查询&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;${} 导致 SQL 注入&lt;a href=&quot;#-导致-sql-注入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;尽量使用 #{}&lt;/li&gt;
&lt;li&gt;必须用 ${} 时（表名/列名/排序），做输入校验&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;自动映射不生效&lt;a href=&quot;#自动映射不生效&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;检查&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;mapUnderscoreToCamelCase 是否设为 true&lt;/li&gt;
&lt;li&gt;autoMappingBehavior 是否为 PARTIAL 或 FULL&lt;/li&gt;
&lt;li&gt;ResultMap 的 autoMapping 是否为 true&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;动态 SQL 中的比较符号问题&lt;a href=&quot;#动态-sql-中的比较符号问题&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;解决&lt;/strong&gt;：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;!-- 方式一：转义 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;if test=&quot;salary &amp;amp;gt; 10000&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- 方式二：CDATA --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;if test=&quot;salary &amp;lt;![CDATA[ &amp;gt; ]]&amp;gt; 10000&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;PageHelper 分页不生效&lt;a href=&quot;#pagehelper-分页不生效&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;检查&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;PageHelper.startPage() 必须在查询方法&lt;strong&gt;前一行&lt;/strong&gt;调用&lt;/li&gt;
&lt;li&gt;确保只对紧随其后的第一个查询生效&lt;/li&gt;
&lt;li&gt;检查插件配置是否正确&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;实战案例集&lt;a href=&quot;#实战案例集&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;案例一：部门员工三级关联查询&lt;a href=&quot;#案例一部门员工三级关联查询&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- 查询部门→员工→项目（三级嵌套） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptEmpProjectResultMap&quot;&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Dept&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;collection&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emps&quot;&lt;/span&gt;&lt;span&gt; ofType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;collection&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;projects&quot;&lt;/span&gt;&lt;span&gt; ofType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Project&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;projectId&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;project_id&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;projectName&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;project_name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;budget&quot;&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;budget&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;collection&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;collection&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectDeptEmpProject&quot;&lt;/span&gt;&lt;span&gt; resultMap&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptEmpProjectResultMap&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        d.dept_id, d.dept_name,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        e.emp_id, e.emp_name, e.salary,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        p.project_id, p.project_name, p.budget&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    FROM dept d&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    LEFT JOIN emp e ON d.dept_id = e.dept_id&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    LEFT JOIN emp_project ep ON e.emp_id = ep.emp_id&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    LEFT JOIN project p ON ep.project_id = p.project_id&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    WHERE d.dept_id = #{deptId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;案例二：通用条件分页查询&lt;a href=&quot;#案例二通用条件分页查询&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; // DTO&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; EmpQueryDTO&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; Integer deptId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; BigDecimal minSalary;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; BigDecimal maxSalary;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; Integer status;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; Integer pageNum &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer pageSize &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 10&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByPage&quot;&lt;/span&gt;&lt;span&gt; resultType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;include&lt;/span&gt;&lt;span&gt; refid&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empColumns&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName != null and empName != &apos;&apos;&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;bind&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;likeName&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&apos;%&apos; + empName + &apos;%&apos;&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             AND emp_name LIKE #{likeName}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            AND dept_id = #{deptId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;minSalary != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            AND salary &lt;/span&gt;&lt;span&gt;&amp;amp;gt;&lt;/span&gt;&lt;span&gt;= #{minSalary}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;maxSalary != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            AND salary &lt;/span&gt;&lt;span&gt;&amp;amp;lt;&lt;/span&gt;&lt;span&gt;= #{maxSalary}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;status != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            AND status = #{status}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;where&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ORDER BY emp_id DESC&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;// Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; PageInfo&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; getEmpPage&lt;/span&gt;&lt;span&gt;(EmpQueryDTO dto) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    PageHelper.&lt;/span&gt;&lt;span&gt;startPage&lt;/span&gt;&lt;span&gt;(dto.&lt;/span&gt;&lt;span&gt;getPageNum&lt;/span&gt;&lt;span&gt;(), dto.&lt;/span&gt;&lt;span&gt;getPageSize&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; list &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper.&lt;/span&gt;&lt;span&gt;selectByPage&lt;/span&gt;&lt;span&gt;(dto);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    return&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; PageInfo&amp;lt;&amp;gt;(list);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;案例三：批量导入（Excel 数据导入）&lt;a href=&quot;#案例三批量导入excel-数据导入&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Transactional&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; batchImport&lt;/span&gt;&lt;span&gt;(List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;EmpDTO&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; dtoList) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; empList &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; dtoList.&lt;/span&gt;&lt;span&gt;stream&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;map&lt;/span&gt;&lt;span&gt;(dto &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         Emp emp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         emp.&lt;/span&gt;&lt;span&gt;setEmpName&lt;/span&gt;&lt;span&gt;(dto.&lt;/span&gt;&lt;span&gt;getName&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         emp.&lt;/span&gt;&lt;span&gt;setEmail&lt;/span&gt;&lt;span&gt;(dto.&lt;/span&gt;&lt;span&gt;getEmail&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         emp.&lt;/span&gt;&lt;span&gt;setSalary&lt;/span&gt;&lt;span&gt;(dto.&lt;/span&gt;&lt;span&gt;getSalary&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         emp.&lt;/span&gt;&lt;span&gt;setDeptId&lt;/span&gt;&lt;span&gt;(dto.&lt;/span&gt;&lt;span&gt;getDeptId&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         emp.&lt;/span&gt;&lt;span&gt;setHireDate&lt;/span&gt;&lt;span&gt;(dto.&lt;/span&gt;&lt;span&gt;getHireDate&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        emp.&lt;/span&gt;&lt;span&gt;setStatus&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; emp;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }).&lt;/span&gt;&lt;span&gt;collect&lt;/span&gt;&lt;span&gt;(Collectors.&lt;/span&gt;&lt;span&gt;toList&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 分批插入，每 500 条一批&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; batchSize &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 500&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    for&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 0&lt;/span&gt;&lt;span&gt;; i &lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt; empList.&lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;(); i &lt;/span&gt;&lt;span&gt;+=&lt;/span&gt;&lt;span&gt; batchSize) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        int&lt;/span&gt;&lt;span&gt; end &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Math.&lt;/span&gt;&lt;span&gt;min&lt;/span&gt;&lt;span&gt;(i &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; batchSize, empList.&lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; batch &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empList.&lt;/span&gt;&lt;span&gt;subList&lt;/span&gt;&lt;span&gt;(i, end);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        empMapper.&lt;/span&gt;&lt;span&gt;batchInsert&lt;/span&gt;&lt;span&gt;(batch);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;案例四：自定义 TypeHandler（JSON 存储）&lt;a href=&quot;#案例四自定义-typehandlerjson-存储&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;// 实体类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // JSON 格式存储到数据库&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;&amp;gt; extInfo;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;MappedTypes&lt;/span&gt;&lt;span&gt;(Map.class)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;MappedJdbcTypes&lt;/span&gt;&lt;span&gt;(JdbcType.VARCHAR)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; JsonTypeHandler&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; BaseTypeHandler&lt;/span&gt;&lt;span&gt;&amp;lt;Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; ObjectMapper mapper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; ObjectMapper&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setNonNullParameter&lt;/span&gt;&lt;span&gt;(PreparedStatement &lt;/span&gt;&lt;span&gt;ps&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; i&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                     Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;parameter&lt;/span&gt;&lt;span&gt;, JdbcType &lt;/span&gt;&lt;span&gt;jdbcType&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     throws&lt;/span&gt;&lt;span&gt; SQLException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            ps.&lt;/span&gt;&lt;span&gt;setString&lt;/span&gt;&lt;span&gt;(i, mapper.&lt;/span&gt;&lt;span&gt;writeValueAsString&lt;/span&gt;&lt;span&gt;(parameter));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (JsonProcessingException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            throw&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; SQLException&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;JSON 序列化失败&quot;&lt;/span&gt;&lt;span&gt;, e);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;getNullableResult&lt;/span&gt;&lt;span&gt;(ResultSet &lt;/span&gt;&lt;span&gt;rs&lt;/span&gt;&lt;span&gt;, String &lt;/span&gt;&lt;span&gt;columnName&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     throws&lt;/span&gt;&lt;span&gt; SQLException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; parse&lt;/span&gt;&lt;span&gt;(rs.&lt;/span&gt;&lt;span&gt;getString&lt;/span&gt;&lt;span&gt;(columnName));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;getNullableResult&lt;/span&gt;&lt;span&gt;(ResultSet &lt;/span&gt;&lt;span&gt;rs&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; columnIndex&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; SQLException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; parse&lt;/span&gt;&lt;span&gt;(rs.&lt;/span&gt;&lt;span&gt;getString&lt;/span&gt;&lt;span&gt;(columnIndex));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;getNullableResult&lt;/span&gt;&lt;span&gt;(CallableStatement &lt;/span&gt;&lt;span&gt;cs&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; columnIndex&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     throws&lt;/span&gt;&lt;span&gt; SQLException {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; parse&lt;/span&gt;&lt;span&gt;(cs.&lt;/span&gt;&lt;span&gt;getString&lt;/span&gt;&lt;span&gt;(columnIndex));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;parse&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;json&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (json &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; ||&lt;/span&gt;&lt;span&gt; json.&lt;/span&gt;&lt;span&gt;isEmpty&lt;/span&gt;&lt;span&gt;()) &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            return&lt;/span&gt;&lt;span&gt; mapper.&lt;/span&gt;&lt;span&gt;readValue&lt;/span&gt;&lt;span&gt;(json, &lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; TypeReference&amp;lt;Map&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Object&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;() {});&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;catch&lt;/span&gt;&lt;span&gt; (JsonProcessingException &lt;/span&gt;&lt;span&gt;e&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            return&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;案例五：SQL 审计拦截器&lt;a href=&quot;#案例五sql-审计拦截器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Intercepts&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Signature&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Executor.class, &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;query&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                args&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {MappedStatement.class, Object.class, RowBounds.class,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     ResultHandler.class}),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Signature&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; Executor.class, &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;update&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                args&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; {MappedStatement.class, Object.class})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; SlowSqlInterceptor&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; Interceptor&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; long&lt;/span&gt;&lt;span&gt; THRESHOLD &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 1000&lt;/span&gt;&lt;span&gt;;  &lt;/span&gt;&lt;span&gt;// 1秒&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Object &lt;/span&gt;&lt;span&gt;intercept&lt;/span&gt;&lt;span&gt;(Invocation &lt;/span&gt;&lt;span&gt;invocation&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Throwable {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        MappedStatement ms &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (MappedStatement) invocation.&lt;/span&gt;&lt;span&gt;getArgs&lt;/span&gt;&lt;span&gt;()[&lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Object parameter &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; invocation.&lt;/span&gt;&lt;span&gt;getArgs&lt;/span&gt;&lt;span&gt;()[&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;];&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        BoundSql boundSql &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ms.&lt;/span&gt;&lt;span&gt;getBoundSql&lt;/span&gt;&lt;span&gt;(parameter);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String sql &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; boundSql.&lt;/span&gt;&lt;span&gt;getSql&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;replaceAll&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\\&lt;/span&gt;&lt;span&gt;s+&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot; &quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        long&lt;/span&gt;&lt;span&gt; start &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; System.&lt;/span&gt;&lt;span&gt;currentTimeMillis&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Object result;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        try&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; invocation.&lt;/span&gt;&lt;span&gt;proceed&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        } &lt;/span&gt;&lt;span&gt;finally&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            long&lt;/span&gt;&lt;span&gt; elapsed &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; System.&lt;/span&gt;&lt;span&gt;currentTimeMillis&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;-&lt;/span&gt;&lt;span&gt; start;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            if&lt;/span&gt;&lt;span&gt; (elapsed &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; THRESHOLD) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                log.&lt;/span&gt;&lt;span&gt;warn&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;[慢SQL] {}ms | {} | {}&quot;&lt;/span&gt;&lt;span&gt;, elapsed, ms.&lt;/span&gt;&lt;span&gt;getId&lt;/span&gt;&lt;span&gt;(), sql);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            } &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                log.&lt;/span&gt;&lt;span&gt;debug&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;[SQL] {}ms | {} | {}&quot;&lt;/span&gt;&lt;span&gt;, elapsed, ms.&lt;/span&gt;&lt;span&gt;getId&lt;/span&gt;&lt;span&gt;(), sql);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; result;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Object &lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;(Object &lt;/span&gt;&lt;span&gt;target&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; Plugin.&lt;/span&gt;&lt;span&gt;wrap&lt;/span&gt;&lt;span&gt;(target, &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setProperties&lt;/span&gt;&lt;span&gt;(Properties &lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt;) {}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;案例六：MyBatis-Plus 完整 CRUD&lt;a href=&quot;#案例六mybatis-plus-完整-crud&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; //&lt;/span&gt;&lt;span&gt; 实体类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @TableName(&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @Data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public class Emp {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @TableId(&lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; IdType&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;AUTO&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; Long empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @TableField(&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String email;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; BigDecimal salary;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer&lt;/span&gt;&lt;span&gt; deptId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @TableField(fill &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; FieldFill&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;INSERT&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDateTime createTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @TableField(fill &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; FieldFill&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;INSERT_UPDATE&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDateTime updateTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @TableLogic&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer&lt;/span&gt;&lt;span&gt; deleted;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; Mapper&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public interface EmpMapper extends BaseMapper&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    //&lt;/span&gt;&lt;span&gt; 自定义查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @Select(&lt;/span&gt;&lt;span&gt;&quot;SELECT e.* FROM emp e WHERE e.salary &amp;gt; #{salary}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; selectHighSalary(@Param(&lt;/span&gt;&lt;span&gt;&quot;salary&quot;&lt;/span&gt;&lt;span&gt;) BigDecimal salary);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public class EmpServiceImpl extends ServiceImpl&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;EmpMapper, Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; implements EmpService {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public &lt;/span&gt;&lt;span&gt;Page&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; getEmpPage(&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; pageNum, &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; pageSize, EmpQueryDTO query) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            new &lt;/span&gt;&lt;span&gt;Page&amp;lt;&amp;gt;&lt;/span&gt;&lt;span&gt;(pageNum, pageSize),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            new LambdaQueryWrapper&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;like&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;StrUtil&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;isNotBlank&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;query&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getEmpName&lt;/span&gt;&lt;span&gt;()), Emp::getEmpName,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     query&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getEmpName&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .eq(&lt;/span&gt;&lt;span&gt;query&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getDeptId&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;, Emp::getDeptId, &lt;/span&gt;&lt;span&gt;query&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getDeptId&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .ge(&lt;/span&gt;&lt;span&gt;query&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getMinSalary&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;, Emp::getSalary, &lt;/span&gt;&lt;span&gt;query&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getMinSalary&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .le(&lt;/span&gt;&lt;span&gt;query&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getMaxSalary&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;, Emp::getSalary, &lt;/span&gt;&lt;span&gt;query&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getMaxSalary&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .eq(Emp::getDeleted, &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .orderByDesc(Emp::getCreateTime)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        );&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; batchUpsert(List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; empList) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;saveOrUpdateBatch&lt;/span&gt;&lt;span&gt;(empList, &lt;/span&gt;&lt;span&gt;500&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empList;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; Controller&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@RequestMapping(&lt;/span&gt;&lt;span&gt;&quot;/emp&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public class EmpController {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @Autowired&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; EmpService empService;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @GetMapping(&lt;/span&gt;&lt;span&gt;&quot;/page&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public Result&lt;/span&gt;&lt;span&gt;&amp;lt;Page&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span&gt; page&lt;/span&gt;&lt;span&gt;(@RequestParam(defaultValue &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;1&quot;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; pageNum,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                   @RequestParam(defaultValue &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;10&quot;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt; pageSize,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                   EmpQueryDTO query) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; Result&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;empService&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;getEmpPage&lt;/span&gt;&lt;span&gt;(pageNum, pageSize, query));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @PostMapping&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public Result&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Void&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; save&lt;/span&gt;&lt;span&gt;(@RequestBody Emp emp) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        empService&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;save&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; Result&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @PutMapping&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public Result&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Void&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; update&lt;/span&gt;&lt;span&gt;(@RequestBody Emp emp) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        empService&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateById&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; Result&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @DeleteMapping(&lt;/span&gt;&lt;span&gt;&quot;/{id}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public Result&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Void&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; delete&lt;/span&gt;&lt;span&gt;(@PathVariable Long id) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        empService&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;removeById&lt;/span&gt;&lt;span&gt;(id);  &lt;/span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; 逻辑删除&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; Result&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;速查手册&lt;a href=&quot;#速查手册&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;核心配置速查&lt;a href=&quot;#核心配置速查&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;配置项&lt;/th&gt;&lt;th&gt;默认值&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;mapUnderscoreToCamelCase&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;下划线命名自动映射为驼峰命名&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;cacheEnabled&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否允许使用映射器二级缓存&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;lazyLoadingEnabled&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否启用延迟加载&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;defaultExecutorType&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;SIMPLE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;默认执行器类型&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;localCacheScope&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;SESSION&lt;/code&gt;&lt;/td&gt;&lt;td&gt;一级缓存作用域&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;jdbcTypeForNull&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;OTHER&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;null&lt;/code&gt; 参数使用的 JDBC 类型&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;useGeneratedKeys&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否允许 JDBC 自动生成主键&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;autoMappingBehavior&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;PARTIAL&lt;/code&gt;&lt;/td&gt;&lt;td&gt;自动映射级别&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;动态 SQL 速查&lt;a href=&quot;#动态-sql-速查&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;元素&lt;/th&gt;&lt;th&gt;用途&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;if&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;条件判断&lt;/td&gt;&lt;td&gt;条件成立时拼接 SQL 片段&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;where&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;生成 &lt;code&gt;WHERE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;自动移除开头多余的 &lt;code&gt;AND&lt;/code&gt; 或 &lt;code&gt;OR&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;set&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;生成 &lt;code&gt;SET&lt;/code&gt;&lt;/td&gt;&lt;td&gt;自动移除末尾多余的逗号&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;choose&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;多分支选择&lt;/td&gt;&lt;td&gt;与 &lt;code&gt;&amp;lt;when&amp;gt;&lt;/code&gt;、&lt;code&gt;&amp;lt;otherwise&amp;gt;&lt;/code&gt; 配合&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;trim&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;自定义裁剪&lt;/td&gt;&lt;td&gt;使用前缀、后缀和覆盖规则调整 SQL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;foreach&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;遍历集合&lt;/td&gt;&lt;td&gt;常用于 &lt;code&gt;IN&lt;/code&gt; 条件和批量写入&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;bind&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;绑定表达式结果&lt;/td&gt;&lt;td&gt;可预先构造供后续引用的变量&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;sql&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;定义 SQL 片段&lt;/td&gt;&lt;td&gt;通过 &lt;code&gt;&amp;lt;include&amp;gt;&lt;/code&gt; 复用&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;关联映射速查&lt;a href=&quot;#关联映射速查&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;元素&lt;/th&gt;&lt;th&gt;用途&lt;/th&gt;&lt;th&gt;常用属性&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;association&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;一对一关联&lt;/td&gt;&lt;td&gt;&lt;code&gt;property&lt;/code&gt;、&lt;code&gt;javaType&lt;/code&gt;、&lt;code&gt;column&lt;/code&gt;、&lt;code&gt;select&lt;/code&gt;、&lt;code&gt;fetchType&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;collection&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;一对多关联&lt;/td&gt;&lt;td&gt;&lt;code&gt;property&lt;/code&gt;、&lt;code&gt;ofType&lt;/code&gt;、&lt;code&gt;column&lt;/code&gt;、&lt;code&gt;select&lt;/code&gt;、&lt;code&gt;fetchType&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;&amp;lt;discriminator&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;根据列值选择映射&lt;/td&gt;&lt;td&gt;&lt;code&gt;column&lt;/code&gt;、&lt;code&gt;javaType&lt;/code&gt;、&lt;code&gt;case&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;参数占位符速查&lt;a href=&quot;#参数占位符速查&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;特性&lt;/th&gt;&lt;th&gt;&lt;code&gt;#{}&lt;/code&gt;&lt;/th&gt;&lt;th&gt;&lt;code&gt;${}&lt;/code&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;处理方式&lt;/td&gt;&lt;td&gt;预编译参数占位&lt;/td&gt;&lt;td&gt;字符串直接替换&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;SQL 注入风险&lt;/td&gt;&lt;td&gt;较低&lt;/td&gt;&lt;td&gt;较高&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;典型用途&lt;/td&gt;&lt;td&gt;参数值&lt;/td&gt;&lt;td&gt;经过白名单校验的表名、列名或排序片段&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;缓存速查&lt;a href=&quot;#缓存速查&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;特性&lt;/th&gt;&lt;th&gt;一级缓存&lt;/th&gt;&lt;th&gt;二级缓存&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;作用域&lt;/td&gt;&lt;td&gt;&lt;code&gt;SqlSession&lt;/code&gt;&lt;/td&gt;&lt;td&gt;Mapper 命名空间&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;默认状态&lt;/td&gt;&lt;td&gt;开启&lt;/td&gt;&lt;td&gt;需要在映射文件中配置&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;常见失效时机&lt;/td&gt;&lt;td&gt;更新、提交、回滚、关闭会话或清空缓存&lt;/td&gt;&lt;td&gt;同命名空间执行更新语句时通常会刷新&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;注解速查&lt;a href=&quot;#注解速查&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;









































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;注解&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@Select&lt;/code&gt;&lt;/td&gt;&lt;td&gt;声明查询语句&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@Insert&lt;/code&gt;&lt;/td&gt;&lt;td&gt;声明插入语句&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@Update&lt;/code&gt;&lt;/td&gt;&lt;td&gt;声明更新语句&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@Delete&lt;/code&gt;&lt;/td&gt;&lt;td&gt;声明删除语句&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@Results&lt;/code&gt;、&lt;code&gt;@Result&lt;/code&gt;&lt;/td&gt;&lt;td&gt;声明结果映射&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@One&lt;/code&gt;、&lt;code&gt;@Many&lt;/code&gt;&lt;/td&gt;&lt;td&gt;声明关联查询&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@Options&lt;/code&gt;&lt;/td&gt;&lt;td&gt;配置主键回填、缓存等选项&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;@Param&lt;/code&gt;&lt;/td&gt;&lt;td&gt;为方法参数命名&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;常见错误速查&lt;a href=&quot;#常见错误速查&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;现象&lt;/th&gt;&lt;th&gt;常见原因&lt;/th&gt;&lt;th&gt;排查方向&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;BindingException&lt;/code&gt;&lt;/td&gt;&lt;td&gt;映射语句未注册&lt;/td&gt;&lt;td&gt;检查命名空间、语句 ID 和映射文件扫描路径&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;找不到属性的 getter&lt;/td&gt;&lt;td&gt;参数名或表达式不匹配&lt;/td&gt;&lt;td&gt;检查 &lt;code&gt;@Param&lt;/code&gt;、实体属性与 OGNL 表达式&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;NotSerializableException&lt;/code&gt;&lt;/td&gt;&lt;td&gt;二级缓存对象不可序列化&lt;/td&gt;&lt;td&gt;让缓存对象实现 &lt;code&gt;Serializable&lt;/code&gt;，或调整缓存实现&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;N+1 查询&lt;/td&gt;&lt;td&gt;嵌套查询逐条执行&lt;/td&gt;&lt;td&gt;评估联表查询、批量查询或延迟加载&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;中文乱码&lt;/td&gt;&lt;td&gt;客户端、连接或数据库编码不一致&lt;/td&gt;&lt;td&gt;统一字符集配置&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;附录：MyBatis 知识体系全景&lt;a href=&quot;#附录mybatis-知识体系全景&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; MyBatis 知识体系&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├── 基础&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   ├── 概述与架构&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   ├── 快速入门&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   ├── 核心配置文件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   └── SqlSession 与映射器&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├── SQL 映射&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   ├── Mapper XML（select/insert/update/delete）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── #{} vs ${}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 参数传递（@Param/Map/对象/List）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── SQL 片段（&amp;lt;sql&amp;gt;/&amp;lt;include&amp;gt;）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── 主键回填（useGeneratedKeys/selectKey）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 结果映射&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── ResultMap（id/result/constructor）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 自动映射（autoMappingBehavior）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── ResultMap 继承（extends）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── 鉴别器（discriminator）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 动态 SQL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── if / where / set&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── choose / when / otherwise&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── trim / foreach / bind&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── SQL 片段复用&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 关联查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 一对一（association）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 一对多（collection）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 多对多&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 嵌套结果 vs 嵌套查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── 延迟加载&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 缓存&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 一级缓存（SqlSession）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 二级缓存（namespace）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 第三方缓存（EhCache/Redis）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── cache-ref&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 高级特性&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── TypeHandler 类型处理器&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── ObjectFactory 对象工厂&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── Plugin 插件机制&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 分页（RowBounds/PageHelper）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── 批量操作（foreach/Batch执行器）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 注解开发&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 基本 CRUD 注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── @Results/@Result&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── @One/@Many&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── @SelectProvider 等&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 框架集成&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── Spring 集成&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── Spring Boot 集成&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── MyBatis-Plus&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 工具&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 代码生成器（MBG/MP Generator）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── 分页插件（PageHelper）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 性能优化&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── SQL 优化&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 缓存策略&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 延迟加载&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 批量操作&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── 连接池调优&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── fetchSize&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└── 排错&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ├── BindingException&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ├── 参数绑定错误&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ├── 编码问题&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ├── 缓存问题&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    └── N+1 问题&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;文档说明&lt;/strong&gt;：本文档全面覆盖了 MyBatis 的所有知识点，从基础概念到高级实战，从理论到指令操作，无遗漏。适合初学者系统学习，也适合有经验的开发者作为参考手册。配合之前的 MySQL（JOIN/子查询/事务/索引）和 Maven 指南使用，可构建完整的 Java 后端知识体系。&lt;/p&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:框架</category><category>tag:MyBatis</category></item><item><title>MyBatis 逆向工程完全指南</title><link>https://blog.hoshiumi.xyz/post/learn/hyxy/framework/mybatis-ni-xiang-gong-cheng-wan-quan-zhi-nan</link><guid isPermaLink="false">learn/hyxy/framework/mybatis-ni-xiang-gong-cheng-wan-quan-zhi-nan</guid><description>MyBatis 逆向工程完全指南
本文档全面覆盖 MyBatis 逆向工程（代码生成器）的所有知识点，包括 MyBatis Generator (MBG) 官方工具与 MyBatis-Plus 代码生成器，从配置到实战，无遗漏。
逆向工程概述
什么是逆向工程
MyBatis</description><pubDate>Thu, 30 Jul 2026 11:30:20 GMT</pubDate><content:encoded>&lt;h1&gt;MyBatis 逆向工程完全指南&lt;a href=&quot;#mybatis-逆向工程完全指南&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;本文档全面覆盖 MyBatis 逆向工程（代码生成器）的所有知识点，包括 MyBatis Generator (MBG) 官方工具与 MyBatis-Plus 代码生成器，从配置到实战，无遗漏。&lt;/p&gt;
&lt;h2&gt;逆向工程概述&lt;a href=&quot;#逆向工程概述&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;什么是逆向工程&lt;a href=&quot;#什么是逆向工程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MyBatis 逆向工程（Reverse Engineering）是指&lt;strong&gt;通过数据库表结构，自动生成 Java 实体类、Mapper 接口、 Mapper XML 映射文件&lt;/strong&gt;的过程。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;数据库表结构  ──→  逆向工程工具  ──→  Java 实体类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    (Generator)       Mapper 接口&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                      Mapper XML&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                      Example 类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                      Service（MP）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                      Controller（MP）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;为什么需要逆向工程&lt;a href=&quot;#为什么需要逆向工程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;传统手写方式&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;逆向工程方式&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;手动创建实体类，逐个字段映射&lt;/td&gt;&lt;td&gt;自动生成，一键完成&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;手写 CRUD 的 SQL 语句&lt;/td&gt;&lt;td&gt;自动生成单表 CRUD&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;容易拼写错误、遗漏字段&lt;/td&gt;&lt;td&gt;与数据库完全一致&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;新增字段需要手动修改多处&lt;/td&gt;&lt;td&gt;重新生成即可&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;耗时且枯燥&lt;/td&gt;&lt;td&gt;秒级完成&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;主流逆向工程工具对比&lt;a href=&quot;#主流逆向工程工具对比&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;工具&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;全称&lt;/th&gt;&lt;th&gt;维护方&lt;/th&gt;&lt;th&gt;特点&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;MyBatis Generator (MBG)&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;MyBatis Generator&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;MyBatis&lt;/strong&gt; 官方&lt;/td&gt;&lt;td&gt;官方&lt;strong&gt;工具&lt;/strong&gt;，稳定可靠，生成实体+Mapper+XML+Example&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;MyBatis-Plus Generator&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;MP Code &lt;strong&gt;Generator&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;MyBatis-Plus&lt;/strong&gt; 社区&lt;/td&gt;&lt;td&gt;功能更强，生成实体+Mapper+XML+Service+Controller，支持模板&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;IDEA 插件（Free MyBatis Tool）&lt;/td&gt;&lt;td&gt;EasyCode、MyBatisCodeHelper&lt;/td&gt;&lt;td&gt;第三方&lt;/td&gt;&lt;td&gt;可视化操作，适合快速开发&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;RuoYi 代码生成器&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;若依&lt;strong&gt;代码生成&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;&lt;strong&gt;RuoYi&lt;/strong&gt; 社区&lt;/td&gt;&lt;td&gt;自带模板引擎，生成完整前后端代码&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;逆向工程能生成什么&lt;a href=&quot;#逆向工程能生成什么&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;MyBatis Generator 生成物：&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;src/main/java/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  └── com/example/entity/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      ├── User.java              ← 实体类（POJO）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      └── UserExample.java       ← 查询条件类（QBC风格）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  └── com/example/mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      └── UserMapper.java        ← Mapper 接口&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;src/main/resources/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  └── mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      └── UserMapper.xml         ← SQL 映射文件&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;MyBatis-Plus Generator 生成物：&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; src/main/java/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;   └── com/example/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       ├── entity/User.java       ← 实体类（含 Lombok / Swagger 注解）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       ├── mapper/UserMapper.java ← Mapper 接口（继承 BaseMapper）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       ├── service/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       │   ├── UserService.java       ← Service 接口&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       │   └── impl/UserServiceImpl.java ← Service 实现&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;       └── controller/UserController.java ← Controller&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; src/main/resources/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  └── mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      └── UserMapper.xml         ← SQL 映射文件（可选）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;MyBatis Generator 核心概念&lt;a href=&quot;#mybatis-generator-核心概念&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;MBG 架构总览&lt;a href=&quot;#mbg-架构总览&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; ┌──────────────────────────────────────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │              MyBatis Generator                    │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │                                                    │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  ┌──────────┐   ┌───────────┐   ┌──────────────┐ │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  │ Database  │   │ Generator  │   │  Generated   │ │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  │  Metadata │──→│   Engine   │──→│    Code      │ │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  │ (JDBC)    │   │ (Java)     │   │  (Java/XML)  │ │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  └──────────┘   └─────┬─────┘   └──────────────┘ │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │                       │                            │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│              ┌────────┴────────┐                   │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│              │  Configuration  │                   │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│              │  (XML / Java)   │                   │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│              └─────────────────┘                   │&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└──────────────────────────────────────────────────┘&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;MBG 工作流程&lt;a href=&quot;#mbg-工作流程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;读取 &lt;code&gt;generatorConfig.xml&lt;/code&gt; 或 Java 配置。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过 JDBC 连接数据库并读取表、字段、主键和注释等元数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;将 JDBC 类型转换为 Java 类型。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;根据运行模式和模板生成实体类、Mapper 接口、XML 映射文件以及可选的 Example 条件类。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;将生成结果写入指定目录。重新生成前应确认覆盖和合并策略，尤其要注意 XML 文件的合并行为。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;MBG 版本说明&lt;a href=&quot;#mbg-版本说明&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MyBatis Generator 使用 &lt;code&gt;1.4.x&lt;/code&gt; 版本系列。本文示例采用 &lt;code&gt;1.4.2&lt;/code&gt;，版本号用于保证示例可复现，不代表任何时点的“最新版本”。&lt;/p&gt;
&lt;p&gt;Maven 坐标使用 &lt;code&gt;org.mybatis.generator:mybatis-generator-core:1.4.2&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;环境准备与依赖&lt;a href=&quot;#环境准备与依赖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;项目目录结构&lt;a href=&quot;#项目目录结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; mybatis-generator-demo/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├── pom.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├── src/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   ├── main/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   │   ├── java/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   │   │   └── com/example/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   │   │       ├── entity/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   │   │       ├── mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   │   │       └── generator/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   │           └── Generator.java&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   └── resources/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │       ├── generatorConfig.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │       └── mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── test/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└── lib/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    └── mysql-connector-j-8.0.33.jar&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Maven 依赖（pom.xml）&lt;a href=&quot;#maven-依赖pomxml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;?&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span&gt; encoding&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;project&lt;/span&gt;&lt;span&gt; xmlns&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://maven.apache.org/POM/4.0.0&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;          xmlns:xsi&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://www.w3.org/2001/XMLSchema-instance&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;          xsi:schemaLocation&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;http://maven.apache.org/POM/4.0.0&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;          http://maven.apache.org/xsd/maven-4.0.0.xsd&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;modelVersion&lt;/span&gt;&lt;span&gt;&amp;gt;4.0.0&amp;lt;/&lt;/span&gt;&lt;span&gt;modelVersion&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.example&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-generator-demo&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.0.0&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;packaging&lt;/span&gt;&lt;span&gt;&amp;gt;jar&amp;lt;/&lt;/span&gt;&lt;span&gt;packaging&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;maven.compiler.source&lt;/span&gt;&lt;span&gt;&amp;gt;17&amp;lt;/&lt;/span&gt;&lt;span&gt;maven.compiler.source&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;maven.compiler.target&lt;/span&gt;&lt;span&gt;&amp;gt;17&amp;lt;/&lt;/span&gt;&lt;span&gt;maven.compiler.target&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;project.build.sourceEncoding&lt;/span&gt;&lt;span&gt;&amp;gt;UTF-8&amp;lt;/&lt;/span&gt;&lt;span&gt;project.build.sourceEncoding&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- MyBatis --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.5.16&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- MySQL 驱动 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;8.0.33&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- MyBatis Generator 核心 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis.generator&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-generator-core&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.4.2&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- Log4j2（可选，用于日志输出） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.apache.logging.log4j&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;log4j-core&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;2.22.1&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;!-- MyBatis Generator Maven 插件 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis.generator&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-generator-maven-plugin&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.4.2&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;!-- 配置文件路径 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;&lt;/span&gt;&lt;span&gt;configurationFile&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        src/main/resources/generatorConfig.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;/&lt;/span&gt;&lt;span&gt;configurationFile&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;!-- 是否覆盖已有文件 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;&lt;/span&gt;&lt;span&gt;overwrite&lt;/span&gt;&lt;span&gt;&amp;gt;true&amp;lt;/&lt;/span&gt;&lt;span&gt;overwrite&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;!-- 是否将 MBG 的输出打印到控制台 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;&lt;/span&gt;&lt;span&gt;verbose&lt;/span&gt;&lt;span&gt;&amp;gt;true&amp;lt;/&lt;/span&gt;&lt;span&gt;verbose&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;/&lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;!-- MySQL 驱动（插件也需要） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;8.0.33&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;project&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;示例数据库&lt;a href=&quot;#示例数据库&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; -- 创建数据库&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; CREATE&lt;/span&gt;&lt;span&gt; DATABASE&lt;/span&gt;&lt;span&gt; IF&lt;/span&gt;&lt;span&gt; NOT&lt;/span&gt;&lt;span&gt; EXISTS&lt;/span&gt;&lt;span&gt; mybatis_demo &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; CHARSET utf8mb4;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; USE&lt;/span&gt;&lt;span&gt; mybatis_demo;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; -- 部门表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; dept&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     dept_id    &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt; PRIMARY KEY&lt;/span&gt;&lt;span&gt; AUTO_INCREMENT COMMENT &lt;/span&gt;&lt;span&gt;&apos;部门ID&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     dept_name  &lt;/span&gt;&lt;span&gt;VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;NOT NULL&lt;/span&gt;&lt;span&gt; COMMENT &lt;/span&gt;&lt;span&gt;&apos;部门名称&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     location&lt;/span&gt;&lt;span&gt;   VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;) COMMENT &lt;/span&gt;&lt;span&gt;&apos;部门位置&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;) COMMENT &lt;/span&gt;&lt;span&gt;&apos;部门表&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-- 员工表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;CREATE&lt;/span&gt;&lt;span&gt; TABLE&lt;/span&gt;&lt;span&gt; emp&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    emp_id      &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt; PRIMARY KEY&lt;/span&gt;&lt;span&gt; AUTO_INCREMENT COMMENT &lt;/span&gt;&lt;span&gt;&apos;员工ID&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    emp_name    &lt;/span&gt;&lt;span&gt;VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;NOT NULL&lt;/span&gt;&lt;span&gt; COMMENT &lt;/span&gt;&lt;span&gt;&apos;员工姓名&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    gender      &lt;/span&gt;&lt;span&gt;CHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;DEFAULT&lt;/span&gt;&lt;span&gt; &apos;M&apos;&lt;/span&gt;&lt;span&gt; COMMENT &lt;/span&gt;&lt;span&gt;&apos;性别 M-男 F-女&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    email       &lt;/span&gt;&lt;span&gt;VARCHAR&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;100&lt;/span&gt;&lt;span&gt;) COMMENT &lt;/span&gt;&lt;span&gt;&apos;邮箱&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    salary      &lt;/span&gt;&lt;span&gt;DECIMAL&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;) COMMENT &lt;/span&gt;&lt;span&gt;&apos;工资&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    dept_id     &lt;/span&gt;&lt;span&gt;INT&lt;/span&gt;&lt;span&gt; COMMENT &lt;/span&gt;&lt;span&gt;&apos;所属部门ID&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    hire_date   &lt;/span&gt;&lt;span&gt;DATE&lt;/span&gt;&lt;span&gt; COMMENT &lt;/span&gt;&lt;span&gt;&apos;入职日期&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    create_time &lt;/span&gt;&lt;span&gt;DATETIME&lt;/span&gt;&lt;span&gt; DEFAULT&lt;/span&gt;&lt;span&gt; CURRENT_TIMESTAMP COMMENT &lt;/span&gt;&lt;span&gt;&apos;创建时间&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    update_time &lt;/span&gt;&lt;span&gt;DATETIME&lt;/span&gt;&lt;span&gt; DEFAULT&lt;/span&gt;&lt;span&gt; CURRENT_TIMESTAMP &lt;/span&gt;&lt;span&gt;ON UPDATE&lt;/span&gt;&lt;span&gt; CURRENT_TIMESTAMP COMMENT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &apos;更新时间&apos;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    FOREIGN KEY&lt;/span&gt;&lt;span&gt; (dept_id) &lt;/span&gt;&lt;span&gt;REFERENCES&lt;/span&gt;&lt;span&gt; dept(dept_id)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;) COMMENT &lt;/span&gt;&lt;span&gt;&apos;员工表&apos;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;-- 插入测试数据&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;INSERT INTO&lt;/span&gt;&lt;span&gt; dept &lt;/span&gt;&lt;span&gt;VALUES&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;研发部&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;北京&apos;&lt;/span&gt;&lt;span&gt;), (&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;市场部&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;上海&apos;&lt;/span&gt;&lt;span&gt;), (&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;财务部&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;广州&apos;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;INSERT INTO&lt;/span&gt;&lt;span&gt; emp &lt;/span&gt;&lt;span&gt;VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;张三&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;M&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;zhangsan@qq.com&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;15000&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;00&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;2020-01-15&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;NOW&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;NOW&lt;/span&gt;&lt;span&gt;()),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;李四&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;F&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;lisi@qq.com&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;12000&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;00&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;2021-03-20&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;NOW&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;NOW&lt;/span&gt;&lt;span&gt;()),&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;王五&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;M&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;wangwu@qq.com&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;18000&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;00&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&apos;2019-07-01&apos;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;NOW&lt;/span&gt;&lt;span&gt;(), &lt;/span&gt;&lt;span&gt;NOW&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;MBG 三种运行方式&lt;a href=&quot;#mbg-三种运行方式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;方式一：Java 代码运行（推荐灵活场景）&lt;a href=&quot;#方式一java-代码运行推荐灵活场景&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.generator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.MyBatisGenerator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.config.xml.ConfigurationParser;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.config.Configuration;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.internal.DefaultShellCallback;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.io.File;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.ArrayList;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Generator&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Exception {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; warnings &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; ArrayList&amp;lt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        boolean&lt;/span&gt;&lt;span&gt; overwrite &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;  &lt;/span&gt;&lt;span&gt;// 是否覆盖已有文件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 指向配置文件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        File configFile &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; File&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;src/main/resources/generatorConfig.xml&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        ConfigurationParser parser &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; ConfigurationParser&lt;/span&gt;&lt;span&gt;(warnings);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Configuration config &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; parser.&lt;/span&gt;&lt;span&gt;parseConfiguration&lt;/span&gt;&lt;span&gt;(configFile);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        DefaultShellCallback callback &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; DefaultShellCallback&lt;/span&gt;&lt;span&gt;(overwrite);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        MyBatisGenerator generator &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; MyBatisGenerator&lt;/span&gt;&lt;span&gt;(config, callback, warnings);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 执行生成&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        generator.&lt;/span&gt;&lt;span&gt;generate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;null&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 打印警告信息&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        for&lt;/span&gt;&lt;span&gt; (String warning &lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span&gt; warnings) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(warning);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;✅ 代码生成完成！&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;运行方式：&lt;/strong&gt; 直接右键 main 方法运行。&lt;/p&gt;
&lt;h3&gt;方式二：Maven 插件运行（推荐常规项目）&lt;a href=&quot;#方式二maven-插件运行推荐常规项目&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;pom.xml 中已配置好插件后，执行命令：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;# 在项目根目录执行&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mvn&lt;/span&gt;&lt;span&gt; mybatis-generator:generate&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 如果配置文件不在默认位置，指定路径&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mvn&lt;/span&gt;&lt;span&gt; mybatis-generator:generate&lt;/span&gt;&lt;span&gt; -DconfigurationFile=src/main/resources/generatorConfig.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 如果不想覆盖已有文件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mvn&lt;/span&gt;&lt;span&gt; mybatis-generator:generate&lt;/span&gt;&lt;span&gt; -Doverwrite=false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;注意：&lt;/strong&gt; Maven 插件方式默认读取 src/main/resources/generatorConfig.xml，如果配置文件放在此路径，无需额外指定。&lt;/p&gt;
&lt;h3&gt;方式三：命令行运行（适合脚本化）&lt;a href=&quot;#方式三命令行运行适合脚本化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;# 1. 准备 mybatis-generator-core 和数据库驱动&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 2. 准备 generatorConfig.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 3. 执行生成命令&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;java&lt;/span&gt;&lt;span&gt; -jar&lt;/span&gt;&lt;span&gt; mybatis-generator-core-1.4.2.jar&lt;/span&gt;&lt;span&gt; -configfile&lt;/span&gt;&lt;span&gt; generatorConfig.xml&lt;/span&gt;&lt;span&gt; -overwrite&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 常用参数：&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# -configfile 指定配置文件路径&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# -overwrite 允许覆盖可覆盖的 Java 文件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# -verbose 输出详细信息&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;三种方式对比&lt;a href=&quot;#三种方式对比&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;特性&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;Java &lt;strong&gt;代码运行&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;Maven &lt;strong&gt;插件&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;命令行&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;灵活性&lt;/td&gt;&lt;td&gt;最高（可编程控制）&lt;/td&gt;&lt;td&gt;中等&lt;/td&gt;&lt;td&gt;最低&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;配置复杂度&lt;/td&gt;&lt;td&gt;中等&lt;/td&gt;&lt;td&gt;低&lt;/td&gt;&lt;td&gt;低&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;适合场景&lt;/td&gt;&lt;td&gt;需要自定义逻辑&lt;/td&gt;&lt;td&gt;日常开发&lt;/td&gt;&lt;td&gt;CI/CD 脚本&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;IDE 支持&lt;/td&gt;&lt;td&gt;直接运行&lt;/td&gt;&lt;td&gt;Maven 面板点击&lt;/td&gt;&lt;td&gt;需手动准备 jar&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;generatorConfig.xml 配置详解&lt;a href=&quot;#generatorconfigxml-配置详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;完整配置模板&lt;a href=&quot;#完整配置模板&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;?&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span&gt; encoding&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!&lt;/span&gt;&lt;span&gt;DOCTYPE&lt;/span&gt;&lt;span&gt; generatorConfiguration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         PUBLIC &quot;-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &quot;http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;generatorConfiguration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- ① 引入外部属性文件 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt; resource&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;generator.properties&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- ② classPathEntry：指定数据库驱动路径（Maven插件方式可省略） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;classPathEntry&lt;/span&gt;&lt;span&gt; location&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;lib/mysql-connector-j-8.0.33.jar&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- ③ context：生成上下文（可配置多个） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mysqlContext&quot;&lt;/span&gt;&lt;span&gt; targetRuntime&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MyBatis3&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     defaultModelType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;conditional&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- ====== 内置插件配置 ====== --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- ④ 序列化插件（让实体类实现 Serializable） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.SerializablePlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- ⑤ ToString 插件（生成 toString 方法） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.ToStringPlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- ⑥ EqualsAndHashCode 插件 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.EqualsAndHashCodePlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- ⑦ Row Bounds 插件（分页用，MySQL 不推荐） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- &amp;lt;plugin type=&quot;org.mybatis.generator.plugins.RowBoundsPlugin&quot;/&amp;gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- ⑧ 虚拟主键插件 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- &amp;lt;plugin type=&quot;org.mybatis.generator.plugins.VirtualKeyPlugin&quot;/&amp;gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- ====== 注释生成器 ====== --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- ⑨ 自定义注释生成器 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;!-- 是否去除自动生成的注释 true：去除 false：保留 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;suppressAllComments&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;!-- 是否生成注释中的日期 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;suppressDate&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;!-- 是否添加数据库表的字段备注 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;addRemarkComments&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- ====== 数据库连接 ====== --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- ⑩ JDBC 连接配置 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;jdbcConnection&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             driverClass&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.driver}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             connectionURL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.url}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             userId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.username}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             password&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.password}&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;!-- MySQL 8.x 需要设置以下属性，才能获取表注释 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;useInformationSchema&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;/&lt;/span&gt;&lt;span&gt;jdbcConnection&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;!-- ====== 类型解析 ====== --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;!-- ⑪ Java 类型解析器 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;javaTypeResolver&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;!-- 是否强制使用 BigDecimal --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;forceBigDecimals&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;!-- 是否使用 JSR-310 日期类型（java.time） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;useJSR310Types&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;/&lt;/span&gt;&lt;span&gt;javaTypeResolver&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;!-- ====== 代码生成器 ====== --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;!-- ⑫ Java 实体类生成器 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;javaModelGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/java&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;!-- 是否让 schema 作为包的后缀 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;enableSubPackages&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;!-- 从数据库返回的值是否清理前后的空格 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;trimStrings&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;!-- 是否为实体类生成构造方法 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;constructorBased&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;!-- 是否不可变（final 类，全参构造，无 setter） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;immutable&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;!-- 父类（所有实体类继承的基类） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;!-- &amp;lt;property name=&quot;rootClass&quot; value=&quot;com.example.BaseEntity&quot;/&amp;gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;/&lt;/span&gt;&lt;span&gt;javaModelGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;!-- ⑬ SQL 映射文件生成器 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;sqlMapGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/resources&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;enableSubPackages&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;/&lt;/span&gt;&lt;span&gt;sqlMapGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;!-- ⑭ Mapper 接口生成器 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;javaClientGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;XMLMAPPER&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/java&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;enableSubPackages&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;!-- 父接口（所有 Mapper 继承的接口） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;!-- &amp;lt;property name=&quot;rootInterface&quot; value=&quot;com.example.BaseMapper&quot;/&amp;gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;javaClientGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- ====== 表配置 ====== --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- ⑮ table：每张表配置一个 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; schema&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mybatis_demo&quot;&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableCountByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableDeleteByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableSelectByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableUpdateByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableDeleteByPrimaryKey&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableInsert&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableSelectByPrimaryKey&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableUpdateByPrimaryKey&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;!-- 主键策略：将自增主键回填到实体 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;generatedKey&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt; sqlStatement&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MySql&quot;&lt;/span&gt;&lt;span&gt; identity&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;!-- 列覆盖：强制指定某列的 Java 类型 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;!-- &amp;lt;columnOverride column=&quot;salary&quot; property=&quot;salary&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      javaType=&quot;java.math.BigDecimal&quot;/&amp;gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;!-- 列忽略：不生成该字段 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;!-- &amp;lt;ignoreColumn column=&quot;create_time&quot;/&amp;gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; schema&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mybatis_demo&quot;&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Dept&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableCountByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableDeleteByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableSelectByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableUpdateByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;generatedKey&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept_id&quot;&lt;/span&gt;&lt;span&gt; sqlStatement&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MySql&quot;&lt;/span&gt;&lt;span&gt; identity&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;generatorConfiguration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;外部属性文件（generator.properties）&lt;a href=&quot;#外部属性文件generatorproperties&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;# generator.properties&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.driver&lt;/span&gt;&lt;span&gt;=com.mysql.cj.jdbc.Driver&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.url&lt;/span&gt;&lt;span&gt;=jdbc:mysql://localhost:3306/mybatis_demo?&lt;/span&gt;&lt;span&gt;useSSL&lt;/span&gt;&lt;span&gt;=false&amp;amp;&lt;/span&gt;&lt;span&gt;serverTimezone&lt;/span&gt;&lt;span&gt;=Asia/Shanghai&amp;amp;&lt;/span&gt;&lt;span&gt;useUnicode&lt;/span&gt;&lt;span&gt;=true&amp;amp;&lt;/span&gt;&lt;span&gt;characterEncoding&lt;/span&gt;&lt;span&gt;=UTF-8&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.username&lt;/span&gt;&lt;span&gt;=root&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;jdbc.password&lt;/span&gt;&lt;span&gt;=123456&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;context 元素详解&lt;a href=&quot;#context-元素详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;context 属性&lt;a href=&quot;#context-属性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&amp;lt;context&amp;gt; 是配置的核心，所有生成规则都在其中定义。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mysqlContext&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         targetRuntime&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MyBatis3&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         defaultModelType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;conditional&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         introspectedColumnImpl&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.internal.db.DatabaseIntrospector&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         autoDelimitKeywords&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         beginningDelimiter&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;`&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         endingDelimiter&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;`&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;








































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;属性&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;th&gt;常用值&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;id&lt;/code&gt;&lt;/td&gt;&lt;td&gt;当前上下文的唯一标识&lt;/td&gt;&lt;td&gt;任意不重复字符串&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;targetRuntime&lt;/code&gt;&lt;/td&gt;&lt;td&gt;选择生成器运行模式&lt;/td&gt;&lt;td&gt;&lt;code&gt;MyBatis3&lt;/code&gt;、&lt;code&gt;MyBatis3Simple&lt;/code&gt;、&lt;code&gt;MyBatis3DynamicSql&lt;/code&gt; 等&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;defaultModelType&lt;/code&gt;&lt;/td&gt;&lt;td&gt;设置模型类结构&lt;/td&gt;&lt;td&gt;&lt;code&gt;conditional&lt;/code&gt;、&lt;code&gt;flat&lt;/code&gt;、&lt;code&gt;hierarchical&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;autoDelimitKeywords&lt;/code&gt;&lt;/td&gt;&lt;td&gt;是否自动为数据库关键字添加分隔符&lt;/td&gt;&lt;td&gt;&lt;code&gt;true&lt;/code&gt;、&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;beginningDelimiter&lt;/code&gt;&lt;/td&gt;&lt;td&gt;关键字起始分隔符&lt;/td&gt;&lt;td&gt;MySQL 通常使用反引号&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;endingDelimiter&lt;/code&gt;&lt;/td&gt;&lt;td&gt;关键字结束分隔符&lt;/td&gt;&lt;td&gt;MySQL 通常使用反引号&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;targetRuntime 详解&lt;a href=&quot;#targetruntime-详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;值&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;th&gt;生成物&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;MyBatis3&lt;/td&gt;&lt;td&gt;默认，生成完整代码&lt;/td&gt;&lt;td&gt;实体 + Example + Mapper + XML（含 Example 方法）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MyBatis3Simple&lt;/td&gt;&lt;td&gt;简化版，不生成 Example&lt;/td&gt;&lt;td&gt;实体 + Mapper + XML（仅基本 CRUD）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MyBatis3DynamicSql&lt;/td&gt;&lt;td&gt;动态 SQL 版（需 MyBatis 3.4.0+）&lt;/td&gt;&lt;td&gt;实体 + Mapper（使用 DSL，无 XML）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MyBatis3Kotlin&lt;/td&gt;&lt;td&gt;Kotlin 版&lt;/td&gt;&lt;td&gt;Kotlin 实体 + DSL Mapper&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;MyBatis3Simple 生成的 Mapper 方法（无 Example）：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;insert()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;deleteByPrimaryKey()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;updateByPrimaryKey()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;selectByPrimaryKey()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;selectAll()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;MyBatis3 生成的 Mapper 方法（有 Example）：&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; insert()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; deleteByPrimaryKey()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; updateByPrimaryKey()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; selectByPrimaryKey()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; selectAll() (Simple 没有)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; countByExample()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; deleteByExample()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; selectByExample()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; updateByExampleSelective()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;updateByExample()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;defaultModelType 详解&lt;a href=&quot;#defaultmodeltype-详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;值&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;th&gt;使用场景&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;conditional&lt;/td&gt;&lt;td&gt;默认。如果表只有一个主键，不生成主键类；有复合主键则生成主键类&lt;/td&gt;&lt;td&gt;大多数场景&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;flat&lt;/td&gt;&lt;td&gt;所有表都生成一个扁平的实体类，主键也作为普通字段&lt;/td&gt;&lt;td&gt;简单单表&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;hierarchical&lt;/td&gt;&lt;td&gt;生成层次结构：主键类继承→基础实体类→带 BLOB 的类&lt;/td&gt;&lt;td&gt;有 BLOB 字段的复杂表&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;hierarchical 模式生成的类结构：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;Emp.java           ← 继承 EmpKey，包含普通字段&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpKey.java        ← 仅包含主键字段&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpWithBLOBs.java  ← 继承 Emp，包含 BLOB 字段（如 TEXT/LONGTEXT）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;jdbcConnection — 数据库连接&lt;a href=&quot;#jdbcconnection--数据库连接&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;基本配置&lt;a href=&quot;#基本配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;jdbcConnection&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    driverClass&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.mysql.cj.jdbc.Driver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    connectionURL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jdbc:mysql://localhost:3306/mybatis_demo?&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    useSSL=false&amp;amp;serverTimezone=Asia/Shanghai&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    userId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;root&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    password&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;123456&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/jdbcConnection&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;MySQL 8.x 特殊配置&lt;a href=&quot;#mysql-8x-特殊配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;jdbcConnection&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     driverClass=&quot;com.mysql.cj.jdbc.Driver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     connectionURL=&quot;jdbc:mysql://localhost:3306/mybatis_demo&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     userId=&quot;root&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     password=&quot;123456&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- ★ 关键：使用 information_schema 获取表/字段注释 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;property name=&quot;useInformationSchema&quot; value=&quot;true&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 其他可选属性 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;nullCatalogMeansCurrent&quot; value=&quot;true&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;characterEncoding&quot; value=&quot;utf-8&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;serverTimezone&quot; value=&quot;Asia/Shanghai&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/jdbcConnection&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;重要：&lt;/strong&gt; MySQL 8.x 默认不返回表注释和字段注释。必须设置 useInformationSchema=true，否则 commentGenerator 的 addRemarkComments 无效。&lt;/p&gt;
&lt;h3&gt;各数据库连接配置参考&lt;a href=&quot;#各数据库连接配置参考&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- MySQL 8.x --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;jdbcConnection&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     driverClass&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.mysql.cj.jdbc.Driver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     connectionURL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jdbc:mysql://localhost:3306/mybatis_demo?&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     useSSL=false&amp;amp;amp;serverTimezone=Asia/Shanghai&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     userId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;root&quot;&lt;/span&gt;&lt;span&gt; password&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;123456&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;property &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;useInformationSchema&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/jdbcConnection&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- PostgreSQL --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;jdbcConnection&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    driverClass&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.postgresql.Driver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    connectionURL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jdbc:postgresql://localhost:5432/mydb&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    userId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;postgres&quot;&lt;/span&gt;&lt;span&gt; password&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;123456&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- Oracle --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;jdbcConnection&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    driverClass&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;oracle.jdbc.OracleDriver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    connectionURL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jdbc:oracle:thin:@localhost:1521:orcl&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    userId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;scott&quot;&lt;/span&gt;&lt;span&gt; password&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;tiger&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;!-- SQL Server --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;jdbcConnection&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    driverClass&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.microsoft.sqlserver.jdbc.SQLServerDriver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    connectionURL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jdbc:sqlserver://localhost:1433;databaseName=mydb&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    userId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;sa&quot;&lt;/span&gt;&lt;span&gt; password&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;123456&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;javaModelGenerator — 实体类生成&lt;a href=&quot;#javamodelgenerator--实体类生成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;基本配置&lt;a href=&quot;#基本配置-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;javaModelGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     targetPackage=&quot;com.example.entity&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     targetProject=&quot;src/main/java&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 是否让 schema 作为包名后缀 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- true: com.example.entity.mybatis_demo.Emp --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- false: com.example.entity.Emp --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;property name=&quot;enableSubPackages&quot; value=&quot;false&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 是否清理从数据库返回的字符串前后的空格 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;trimStrings&quot; value=&quot;true&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 是否基于构造方法（生成全参构造 + setter） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;constructorBased&quot; value=&quot;false&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 是否生成不可变类（final + 全参构造 + 无 setter） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;immutable&quot; value=&quot;false&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 所有实体类的父类 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- &amp;lt;property name=&quot;rootClass&quot; value=&quot;com.example.BaseEntity&quot;/&amp;gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/javaModelGenerator&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;生成的实体类示例&lt;a href=&quot;#生成的实体类示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;配置：&lt;/strong&gt; targetPackage=“com.example.entity”, trimStrings=“true”&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.entity;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.math.BigDecimal;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.time.LocalDate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.time.LocalDateTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; Integer empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String gender;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String email;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; BigDecimal salary;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer deptId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDate hireDate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDateTime createTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDateTime updateTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // ====== 构造方法 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;empId&lt;/span&gt;&lt;span&gt;, String &lt;/span&gt;&lt;span&gt;empName&lt;/span&gt;&lt;span&gt;, String &lt;/span&gt;&lt;span&gt;gender&lt;/span&gt;&lt;span&gt;, String &lt;/span&gt;&lt;span&gt;email&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               BigDecimal &lt;/span&gt;&lt;span&gt;salary&lt;/span&gt;&lt;span&gt;, Integer &lt;/span&gt;&lt;span&gt;deptId&lt;/span&gt;&lt;span&gt;, LocalDate &lt;/span&gt;&lt;span&gt;hireDate&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               LocalDateTime &lt;/span&gt;&lt;span&gt;createTime&lt;/span&gt;&lt;span&gt;, LocalDateTime &lt;/span&gt;&lt;span&gt;updateTime&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.empId &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.empName &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empName &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; ?&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; :&lt;/span&gt;&lt;span&gt; empName.&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.gender &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; gender;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.email &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; email &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; ?&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; :&lt;/span&gt;&lt;span&gt; email.&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.salary &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; salary;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.deptId &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; deptId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.hireDate &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; hireDate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.createTime &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; createTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.updateTime &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; updateTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // ====== getter / setter ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Integer &lt;/span&gt;&lt;span&gt;getEmpId&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setEmpId&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;empId&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.empId &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;getEmpName&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setEmpName&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;empName&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.empName &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empName &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; ?&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; :&lt;/span&gt;&lt;span&gt; empName.&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // ... 其他 getter/setter 省略 ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;rootClass 示例&lt;a href=&quot;#rootclass-示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;// BaseEntity.java — 所有实体类的父类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.example.entity;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.time.LocalDateTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; abstract&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; BaseEntity&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDateTime createTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDateTime updateTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // getter / setter&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; LocalDateTime &lt;/span&gt;&lt;span&gt;getCreateTime&lt;/span&gt;&lt;span&gt;() { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; createTime; }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setCreateTime&lt;/span&gt;&lt;span&gt;(LocalDateTime &lt;/span&gt;&lt;span&gt;createTime&lt;/span&gt;&lt;span&gt;) { &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.createTime &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; createTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; LocalDateTime &lt;/span&gt;&lt;span&gt;getUpdateTime&lt;/span&gt;&lt;span&gt;() { &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; updateTime; }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setUpdateTime&lt;/span&gt;&lt;span&gt;(LocalDateTime &lt;/span&gt;&lt;span&gt;updateTime&lt;/span&gt;&lt;span&gt;) { &lt;/span&gt;&lt;span&gt;this&lt;/span&gt;&lt;span&gt;.updateTime &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; updateTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;配置 rootClass 后，create_time 和 update_time 字段不会被重复生成在子类中。&lt;/p&gt;
&lt;h2&gt;sqlMapGenerator — XML 映射文件生成&lt;a href=&quot;#sqlmapgenerator--xml-映射文件生成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;基本配置&lt;a href=&quot;#基本配置-2&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;sqlMapGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    targetPackage=&quot;mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    targetProject=&quot;src/main/resources&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;enableSubPackages&quot; value=&quot;false&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/sqlMapGenerator&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;生成的 XML 示例（EmpMapper.xml）&lt;a href=&quot;#生成的-xml-示例empmapperxml&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;?&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span&gt; encoding&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!&lt;/span&gt;&lt;span&gt;DOCTYPE&lt;/span&gt;&lt;span&gt; mapper&lt;/span&gt;&lt;span&gt; PUBLIC &quot;-//mybatis.org//DTD Mapper 3.0//EN&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt; namespace&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.EmpMapper&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;BaseResultMap&quot;&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity.Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt; jdbcType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;INTEGER&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName&quot;&lt;/span&gt;&lt;span&gt; jdbcType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;VARCHAR&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;gender&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;gender&quot;&lt;/span&gt;&lt;span&gt; jdbcType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;CHAR&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email&quot;&lt;/span&gt;&lt;span&gt; jdbcType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;VARCHAR&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary&quot;&lt;/span&gt;&lt;span&gt; jdbcType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;DECIMAL&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept_id&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId&quot;&lt;/span&gt;&lt;span&gt; jdbcType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;INTEGER&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;hire_date&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;hireDate&quot;&lt;/span&gt;&lt;span&gt; jdbcType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;DATE&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;create_time&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;createTime&quot;&lt;/span&gt;&lt;span&gt; jdbcType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;TIMESTAMP&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;update_time&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;updateTime&quot;&lt;/span&gt;&lt;span&gt; jdbcType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;TIMESTAMP&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 通用列名 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;sql&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Base_Column_List&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        emp_id, emp_name, gender, email, salary, dept_id, hire_date, create_time,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        update_time&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;sql&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 按主键查询 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectByPrimaryKey&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;java.lang.Integer&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            resultMap&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;BaseResultMap&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SELECT&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;include&lt;/span&gt;&lt;span&gt; refid&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Base_Column_List&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        WHERE emp_id = #{empId,jdbcType=INTEGER}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 删除 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deleteByPrimaryKey&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;java.lang.Integer&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        DELETE FROM emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        WHERE emp_id = #{empId,jdbcType=INTEGER}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;delete&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 插入 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;insert&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity.Emp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            useGeneratedKeys&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt; keyProperty&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        INSERT INTO emp (emp_name, gender, email,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                         salary, dept_id, hire_date,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                         create_time, update_time)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        VALUES (#{empName,jdbcType=VARCHAR}, #{gender,jdbcType=CHAR},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                #{email,jdbcType=VARCHAR}, #{salary,jdbcType=DECIMAL},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                #{deptId,jdbcType=INTEGER}, #{hireDate,jdbcType=DATE},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 选择性插入（null 字段不插入） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;insertSelective&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity.Emp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            useGeneratedKeys&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt; keyProperty&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        INSERT INTO emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt; prefix&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;(&quot;&lt;/span&gt;&lt;span&gt; suffix&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;)&quot;&lt;/span&gt;&lt;span&gt; suffixOverrides&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;,&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;emp_name,&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;gender != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;gender,&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;email,&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;salary,&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;dept_id,&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;hireDate != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;hire_date,&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;createTime != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;create_time,&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;updateTime != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;update_time,&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt; prefix&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;VALUES (&quot;&lt;/span&gt;&lt;span&gt; suffix&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;)&quot;&lt;/span&gt;&lt;span&gt; suffixOverrides&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;,&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;#{empName,jdbcType=VARCHAR},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;gender != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;#{gender,jdbcType=CHAR},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;#{email,jdbcType=VARCHAR},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;#{salary,jdbcType=DECIMAL},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;#{deptId,jdbcType=INTEGER},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;hireDate != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;#{hireDate,jdbcType=DATE},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;createTime != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;#{createTime,jdbcType=TIMESTAMP},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;updateTime != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;#{updateTime,jdbcType=TIMESTAMP},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 选择性更新 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;updateByPrimaryKeySelective&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity.Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         UPDATE emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;emp_name = #{empName,jdbcType=VARCHAR},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;gender != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;gender = #{gender,jdbcType=CHAR},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;email != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;email = #{email,jdbcType=VARCHAR},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;salary = #{salary,jdbcType=DECIMAL},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptId != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;dept_id = #{deptId,jdbcType=INTEGER},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;hireDate != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;hire_date = #{hireDate,jdbcType=DATE},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;createTime != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;create_time = #&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      {createTime,jdbcType=TIMESTAMP},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; test&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;updateTime != null&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;update_time = #&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      {updateTime,jdbcType=TIMESTAMP},&amp;lt;/&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;/&lt;/span&gt;&lt;span&gt;set&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         WHERE emp_id = #{empId,jdbcType=INTEGER}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 全量更新 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;updateByPrimaryKey&quot;&lt;/span&gt;&lt;span&gt; parameterType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity.Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         UPDATE emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         SET emp_name    = #{empName,jdbcType=VARCHAR},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             gender      = #{gender,jdbcType=CHAR},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             email       = #{email,jdbcType=VARCHAR},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             salary      = #{salary,jdbcType=DECIMAL},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            dept_id     = #{deptId,jdbcType=INTEGER},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            hire_date   = #{hireDate,jdbcType=DATE},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            create_time = #{createTime,jdbcType=TIMESTAMP},&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            update_time = #{updateTime,jdbcType=TIMESTAMP}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        WHERE emp_id = #{empId,jdbcType=INTEGER}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;update&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;javaClientGenerator — Mapper 接口生成&lt;a href=&quot;#javaclientgenerator--mapper-接口生成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;基本配置&lt;a href=&quot;#基本配置-3&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;javaClientGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;XMLMAPPER&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/java&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;enableSubPackages&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;javaClientGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;type&lt;/code&gt; 属性&lt;a href=&quot;#type-属性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;值&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;th&gt;生成物&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;XMLMAPPER&lt;/code&gt;&lt;/td&gt;&lt;td&gt;接口与 XML 映射文件分离，适合大多数项目&lt;/td&gt;&lt;td&gt;Mapper 接口与对应 XML&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ANNOTATEDMAPPER&lt;/code&gt;&lt;/td&gt;&lt;td&gt;SQL 主要通过注解写在接口中&lt;/td&gt;&lt;td&gt;Mapper 接口，无独立 XML&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;MIXEDMAPPER&lt;/code&gt;&lt;/td&gt;&lt;td&gt;基础语句使用注解，复杂语句保留 XML&lt;/td&gt;&lt;td&gt;Mapper 接口与部分 XML&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;生成的 Mapper 接口示例（XMLMAPPER 模式）&lt;a href=&quot;#生成的-mapper-接口示例xmlmapper-模式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.mapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.example.entity.Emp;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.example.entity.EmpExample;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.annotations.Param;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; EmpMapper&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // ====== 按 Example 查询 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    long&lt;/span&gt;&lt;span&gt; countByExample&lt;/span&gt;&lt;span&gt;(EmpExample &lt;/span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; deleteByExample&lt;/span&gt;&lt;span&gt;(EmpExample &lt;/span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;selectByExample&lt;/span&gt;&lt;span&gt;(EmpExample &lt;/span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; updateByExampleSelective&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;Param&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;record&quot;&lt;/span&gt;&lt;span&gt;) Emp &lt;/span&gt;&lt;span&gt;record&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                  @&lt;/span&gt;&lt;span&gt;Param&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;example&quot;&lt;/span&gt;&lt;span&gt;) EmpExample &lt;/span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; updateByExample&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;Param&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;record&quot;&lt;/span&gt;&lt;span&gt;) Emp &lt;/span&gt;&lt;span&gt;record&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                         @&lt;/span&gt;&lt;span&gt;Param&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;example&quot;&lt;/span&gt;&lt;span&gt;) EmpExample &lt;/span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // ====== 按主键操作 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; deleteByPrimaryKey&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;empId&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; insert&lt;/span&gt;&lt;span&gt;(Emp &lt;/span&gt;&lt;span&gt;record&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; insertSelective&lt;/span&gt;&lt;span&gt;(Emp &lt;/span&gt;&lt;span&gt;record&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    Emp &lt;/span&gt;&lt;span&gt;selectByPrimaryKey&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;empId&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; updateByPrimaryKeySelective&lt;/span&gt;&lt;span&gt;(Emp &lt;/span&gt;&lt;span&gt;record&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    int&lt;/span&gt;&lt;span&gt; updateByPrimaryKey&lt;/span&gt;&lt;span&gt;(Emp &lt;/span&gt;&lt;span&gt;record&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;ANNOTATEDMAPPER 模式生成的接口&lt;a href=&quot;#annotatedmapper-模式生成的接口&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;// 纯注解，没有 XML 文件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; EmpMapper&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Insert&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;INSERT INTO emp (emp_name, gender, ...)&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;VALUES (#{empName,jdbcType=VARCHAR}, #{gender,jdbcType=CHAR}, ...)&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;useGeneratedKeys&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;keyProperty&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;empId&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     int&lt;/span&gt;&lt;span&gt; insert&lt;/span&gt;&lt;span&gt;(Emp &lt;/span&gt;&lt;span&gt;record&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Select&lt;/span&gt;&lt;span&gt;({&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;SELECT emp_id, emp_name, gender, ...&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;FROM emp&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &quot;WHERE emp_id = #{empId,jdbcType=INTEGER}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;ResultMap&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;BaseResultMap&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    Emp &lt;/span&gt;&lt;span&gt;selectByPrimaryKey&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;empId&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // ... 其他方法&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;table 元素详解&lt;a href=&quot;#table-元素详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;table 完整属性&lt;a href=&quot;#table-完整属性&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     schema&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mybatis_demo&quot;&lt;/span&gt;&lt;span&gt;           &amp;lt;!-- 数据库名/schema --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     tableName=&quot;emp&quot;                  &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 数据库表名（支持通配符 %） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     domainObjectName=&quot;Emp&quot;           &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 生成的实体类名 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     mapperName=&quot;EmpMapper&quot;           &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 生成的 Mapper 接口名（可含包名） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     sqlMapName=&quot;EmpMapper&quot;           &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 生成的 XML 文件名 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     alias=&quot;e&quot;                        &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 表别名（用于多表查询） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     enableCountByExample=&quot;true&quot;      &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 是否生成 countByExample --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     enableDeleteByExample=&quot;true&quot;     &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 是否生成 deleteByExample --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    enableSelectByExample=&quot;true&quot;     &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 是否生成 selectByExample --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    enableUpdateByExample=&quot;true&quot;     &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 是否生成 updateByExample --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    enableDeleteByPrimaryKey=&quot;true&quot;  &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 是否生成 deleteByPrimaryKey --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    enableInsert=&quot;true&quot;              &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 是否生成 insert --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    enableSelectByPrimaryKey=&quot;true&quot;  &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 是否生成 selectByPrimaryKey --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    enableUpdateByPrimaryKey=&quot;true&quot;  &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 是否生成 updateByPrimaryKey --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    selectByPrimaryKeyQueryId=&quot;false&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    selectByExampleQueryId=&quot;false&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    modelType=&quot;conditional&quot;          &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 覆盖 context 的 defaultModelType --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    delimitIdentifiers=&quot;false&quot;       &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 是否给所有标识符加分隔符 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    delimitAllColumns=&quot;false&quot;        &lt;/span&gt;&lt;span&gt;&amp;lt;!-- 是否给所有列加分隔符 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;tableName 通配符用法&lt;a href=&quot;#tablename-通配符用法&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- 生成所有表（慎用） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;%&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- 生成所有以 t_ 开头的表 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;t_%&quot;&lt;/span&gt;&lt;span&gt; /&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- 排除某些表（需配合 table 的 schema 属性） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;%&quot;&lt;/span&gt;&lt;span&gt; &amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 通过 domainObjectRenamingRule 来调整命名 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;generatedKey — 主键回填&lt;a href=&quot;#generatedkey--主键回填&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 方式一：MySQL 自增主键 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;generatedKey&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt; sqlStatement&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MySql&quot;&lt;/span&gt;&lt;span&gt; identity&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 方式二：SQL Server 自增主键 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- &amp;lt;generatedKey column=&quot;id&quot; sqlStatement=&quot;SQL Server&quot; identity=&quot;true&quot;/&amp;gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 方式三：Oracle 序列 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- &amp;lt;generatedKey column=&quot;id&quot; sqlStatement=&quot;select SEQ_EMP.nextval from dual&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     identity=&quot;false&quot;/&amp;gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 方式四：PostgreSQL --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- &amp;lt;generatedKey column=&quot;id&quot; sqlStatement=&quot;PostgreSQL&quot; identity=&quot;true&quot;/&amp;gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;属性&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;column&lt;/code&gt;&lt;/td&gt;&lt;td&gt;主键列名&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;sqlStatement&lt;/code&gt;&lt;/td&gt;&lt;td&gt;获取主键值的语句或数据库标识，例如 MySQL 常用 &lt;code&gt;MySql&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;identity&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;true&lt;/code&gt; 表示数据库自增主键；&lt;code&gt;false&lt;/code&gt; 表示由语句取得主键值&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;type&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;pre&lt;/code&gt; 表示插入前获取主键，&lt;code&gt;post&lt;/code&gt; 表示插入后获取主键&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;columnOverride — 列覆盖&lt;a href=&quot;#columnoverride--列覆盖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 强制指定某列的 Java 类型和 jdbcType --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;columnOverride&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    javaType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;java.math.BigDecimal&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    jdbcType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;DECIMAL&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 强制指定枚举类型 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;columnOverride&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;gender&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;gender&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    javaType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.enums.Gender&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    typeHandler&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.handler.GenderTypeHandler&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 修改属性名（驼峰自定义） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;columnOverride&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;name&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 强制 BLOB 类型 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;columnOverride&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;content&quot;&lt;/span&gt;&lt;span&gt; isBlob&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt; javaType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;java.lang.String&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;ignoreColumn — 忽略列&lt;a href=&quot;#ignorecolumn--忽略列&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 不生成这些字段 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;ignoreColumn&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;create_time&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;ignoreColumn&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;update_time&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 支持正则匹配 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- &amp;lt;ignoreColumn pattern=&quot;^temp_.*&quot;/&amp;gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;domainObjectRenamingRule — 实体类重命名规则&lt;a href=&quot;#domainobjectrenamingrule--实体类重命名规则&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;t_emp&quot;&lt;/span&gt;&lt;span&gt; domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 去掉表名前缀 t_ --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;domainObjectRenamingRule&lt;/span&gt;&lt;span&gt; searchString&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;^T_&quot;&lt;/span&gt;&lt;span&gt; replaceString&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;columnRenamingRule — 列重命名规则&lt;a href=&quot;#columnrenamingrule--列重命名规则&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 去掉列名前缀 F_ --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;columnRenamingRule&lt;/span&gt;&lt;span&gt; searchString&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;^F_&quot;&lt;/span&gt;&lt;span&gt; replaceString&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;生成的代码结构说明&lt;a href=&quot;#生成的代码结构说明&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;完整目录结构&lt;a href=&quot;#完整目录结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;mybatis-generator-demo/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── src/main/java/com/example/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── entity/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   ├── Emp.java              ← 员工实体类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   ├── EmpExample.java       ← 员工查询条件类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   ├── Dept.java             ← 部门实体类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   └── DeptExample.java      ← 部门查询条件类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   │   ├── EmpMapper.java        ← 员工 Mapper 接口&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   └── DeptMapper.java       ← 部门 Mapper 接口&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── generator/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│       └── Generator.java        ← 生成器启动类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── src/main/resources/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── generatorConfig.xml       ← MBG 配置文件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── generator.properties      ← 属性文件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   ├── EmpMapper.xml         ← 员工 SQL 映射&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   └── DeptMapper.xml        ← 部门 SQL 映射&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── mybatis-config.xml        ← MyBatis 主配置&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└── pom.xml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;各方法功能对照表&lt;a href=&quot;#各方法功能对照表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;方法&lt;/strong&gt;功能对应 &lt;strong&gt;SQL&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;INSERT INTO emp (…) VALUES insert(Emp record)插入全部字段(…)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;insertSelective&lt;/span&gt;&lt;span&gt;(Emp record)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;选择性插入（null 字 INSERT INTO emp (…) VALUES 段不插入）(…) + &lt;/p&gt;
&lt;p&gt;DELETE FROM emp WHERE emp_id deleteByPrimaryKey(Integer id)按主键删除= ?&lt;/p&gt;
&lt;p&gt;deleteByExample(EmpExample example)按条件删除 DELETE FROM emp WHERE …&lt;/p&gt;
&lt;p&gt;UPDATE emp SET … WHERE updateByPrimaryKey(Emp record)全量更新 emp_id = ?&lt;/p&gt;
&lt;p&gt;updateByPrimaryKeySelective(EmpUPDATE emp SET … WHERE 选择性更新 record)emp_id = ? + &lt;/p&gt;
&lt;p&gt;updateByExample(…)按条件全量更新 UPDATE emp SET … WHERE …&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; UPDATE&lt;/span&gt;&lt;span&gt; emp &lt;/span&gt;&lt;span&gt;SET&lt;/span&gt;&lt;span&gt; ... &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &amp;lt;if&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;updateByExampleSelective(…)按条件选择性更新&lt;/p&gt;
&lt;p&gt;SELECT … FROM emp WHERE selectByPrimaryKey(Integer id)按主键查询 emp_id = ?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; SELECT&lt;/span&gt;&lt;span&gt; ... &lt;/span&gt;&lt;span&gt;FROM&lt;/span&gt;&lt;span&gt; emp &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;selectByExample(EmpExample example)按条件查询&lt;/p&gt;
&lt;p&gt;SELECT COUNT(*) FROM emp countByExample(EmpExample example)按条件计数 WHERE …&lt;/p&gt;
&lt;h2&gt;Example 类详解（QBC 风格查询）&lt;a href=&quot;#example-类详解qbc-风格查询&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Example 类的作用&lt;a href=&quot;#example-类的作用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Example 类是 MBG 自动生成的&lt;strong&gt;查询条件构造器&lt;/strong&gt;，采用 &lt;strong&gt;QBC（Query By Criteria）&lt;/strong&gt; 风格，通过链式调用构建 WHERE 条件，避免手写 SQL。&lt;/p&gt;
&lt;h3&gt;Example 类结构&lt;a href=&quot;#example-类结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; EmpExample&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     protected&lt;/span&gt;&lt;span&gt; String orderByClause;          &lt;/span&gt;&lt;span&gt;// 排序字段&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     protected&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; distinct;              &lt;/span&gt;&lt;span&gt;// 是否去重&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     protected&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;Criteria&lt;/span&gt;&lt;span&gt;&amp;gt; oredCriteria;   &lt;/span&gt;&lt;span&gt;// OR 条件列表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     // 设置排序&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setOrderByClause&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;orderByClause&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     // 设置去重&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setDistinct&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;boolean&lt;/span&gt;&lt;span&gt; distinct&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 获取 OR 条件列表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;Criteria&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;getOredCriteria&lt;/span&gt;&lt;span&gt;() { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 创建一个 OR 条件（相当于 OR (...)）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;or&lt;/span&gt;&lt;span&gt;() { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 添加一个 Criteria 到 OR 列表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; or&lt;/span&gt;&lt;span&gt;(Criteria &lt;/span&gt;&lt;span&gt;criteria&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 创建一个 Criteria（相当于一个 AND 条件组）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;() { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // = createCriteria()，内部调用&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    protected&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;createCriteriaInternal&lt;/span&gt;&lt;span&gt;() { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 清空所有条件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; clear&lt;/span&gt;&lt;span&gt;() { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // ====== Criteria 内部类 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; abstract&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; GeneratedCriteria&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 等于&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpIdEqualTo&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 不等于&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpIdNotEqualTo&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 大于&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpIdGreaterThan&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 大于等于&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpIdGreaterThanOrEqualTo&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 小于&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpIdLessThan&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 小于等于&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpIdLessThanOrEqualTo&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // IN&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpIdIn&lt;/span&gt;&lt;span&gt;(List&amp;lt;&lt;/span&gt;&lt;span&gt;Integer&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;values&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // NOT IN&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpIdNotIn&lt;/span&gt;&lt;span&gt;(List&amp;lt;&lt;/span&gt;&lt;span&gt;Integer&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;values&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // BETWEEN&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpIdBetween&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;value1&lt;/span&gt;&lt;span&gt;, Integer &lt;/span&gt;&lt;span&gt;value2&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // NOT BETWEEN&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpIdNotBetween&lt;/span&gt;&lt;span&gt;(Integer &lt;/span&gt;&lt;span&gt;value1&lt;/span&gt;&lt;span&gt;, Integer &lt;/span&gt;&lt;span&gt;value2&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // LIKE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpNameLike&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // NOT LIKE&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpNameNotLike&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;) { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // IS NULL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpNameIsNull&lt;/span&gt;&lt;span&gt;() { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // IS NOT NULL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        public&lt;/span&gt;&lt;span&gt; Criteria &lt;/span&gt;&lt;span&gt;andEmpNameIsNotNull&lt;/span&gt;&lt;span&gt;() { ... }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // ... 每个字段都有以上方法&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // ====== Criteria 继承类 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Criteria&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; GeneratedCriteria&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // ...&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Example 常用查询示例&lt;a href=&quot;#example-常用查询示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; //&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;span&gt;. 查询所有 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; allEmps &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;selectByExample&lt;/span&gt;&lt;span&gt;(new EmpExample());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; //&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 2&lt;/span&gt;&lt;span&gt;. 按主键查询 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; Emp emp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;selectByPrimaryKey&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; //&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 3&lt;/span&gt;&lt;span&gt;. 等值查询：gender &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &apos;M&apos;&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new EmpExample();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;().andGenderEqualTo(&lt;/span&gt;&lt;span&gt;&quot;M&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; males &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;selectByExample&lt;/span&gt;&lt;span&gt;(example);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 4&lt;/span&gt;&lt;span&gt;. 多条件 &lt;/span&gt;&lt;span&gt;AND&lt;/span&gt;&lt;span&gt; 查询 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; WHERE&lt;/span&gt;&lt;span&gt; gender &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &apos;M&apos;&lt;/span&gt;&lt;span&gt; AND&lt;/span&gt;&lt;span&gt; salary &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; 10000&lt;/span&gt;&lt;span&gt; AND&lt;/span&gt;&lt;span&gt; dept_id &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new EmpExample();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .andGenderEqualTo(&lt;/span&gt;&lt;span&gt;&quot;M&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .andSalaryGreaterThan(new BigDecimal(&lt;/span&gt;&lt;span&gt;&quot;10000&quot;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .andDeptIdEqualTo(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;selectByExample&lt;/span&gt;&lt;span&gt;(example);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 5&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;OR&lt;/span&gt;&lt;span&gt; 条件查询 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; WHERE&lt;/span&gt;&lt;span&gt; (gender &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &apos;M&apos;&lt;/span&gt;&lt;span&gt; AND&lt;/span&gt;&lt;span&gt; salary &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; 15000&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;OR&lt;/span&gt;&lt;span&gt; (gender &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &apos;F&apos;&lt;/span&gt;&lt;span&gt; AND&lt;/span&gt;&lt;span&gt; salary &lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; 12000&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new EmpExample();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .andGenderEqualTo(&lt;/span&gt;&lt;span&gt;&quot;M&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .andSalaryGreaterThan(new BigDecimal(&lt;/span&gt;&lt;span&gt;&quot;15000&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;or&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .andGenderEqualTo(&lt;/span&gt;&lt;span&gt;&quot;F&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .andSalaryGreaterThan(new BigDecimal(&lt;/span&gt;&lt;span&gt;&quot;12000&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;selectByExample&lt;/span&gt;&lt;span&gt;(example);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 6&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;LIKE&lt;/span&gt;&lt;span&gt; 查询 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; WHERE&lt;/span&gt;&lt;span&gt; emp_name &lt;/span&gt;&lt;span&gt;LIKE&lt;/span&gt;&lt;span&gt; &apos;%张%&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new EmpExample();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;().andEmpNameLike(&lt;/span&gt;&lt;span&gt;&quot;%张%&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;selectByExample&lt;/span&gt;&lt;span&gt;(example);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 7&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;IN&lt;/span&gt;&lt;span&gt; 查询 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; WHERE&lt;/span&gt;&lt;span&gt; dept_id &lt;/span&gt;&lt;span&gt;IN&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new EmpExample();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;().andDeptIdIn(&lt;/span&gt;&lt;span&gt;Arrays&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;asList&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;2&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;selectByExample&lt;/span&gt;&lt;span&gt;(example);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 8&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;BETWEEN&lt;/span&gt;&lt;span&gt; 查询 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; WHERE&lt;/span&gt;&lt;span&gt; salary &lt;/span&gt;&lt;span&gt;BETWEEN&lt;/span&gt;&lt;span&gt; 8000&lt;/span&gt;&lt;span&gt; AND&lt;/span&gt;&lt;span&gt; 20000&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new EmpExample();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .andSalaryBetween(new BigDecimal(&lt;/span&gt;&lt;span&gt;&quot;8000&quot;&lt;/span&gt;&lt;span&gt;), new BigDecimal(&lt;/span&gt;&lt;span&gt;&quot;20000&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;selectByExample&lt;/span&gt;&lt;span&gt;(example);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 9&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;IS&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;span&gt; 查询 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; WHERE&lt;/span&gt;&lt;span&gt; email &lt;/span&gt;&lt;span&gt;IS&lt;/span&gt;&lt;span&gt; NULL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new EmpExample();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;().andEmailIsNull();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;selectByExample&lt;/span&gt;&lt;span&gt;(example);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 10&lt;/span&gt;&lt;span&gt;. 排序 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; ORDER BY&lt;/span&gt;&lt;span&gt; salary &lt;/span&gt;&lt;span&gt;DESC&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new EmpExample();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setOrderByClause&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;salary DESC&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;selectByExample&lt;/span&gt;&lt;span&gt;(example);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 11&lt;/span&gt;&lt;span&gt;. 去重 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new EmpExample();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setDistinct&lt;/span&gt;&lt;span&gt;(true);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setOrderByClause&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;dept_id&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; result &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;selectByExample&lt;/span&gt;&lt;span&gt;(example);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 12&lt;/span&gt;&lt;span&gt;. 条件删除 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; DELETE&lt;/span&gt;&lt;span&gt; FROM&lt;/span&gt;&lt;span&gt; emp &lt;/span&gt;&lt;span&gt;WHERE&lt;/span&gt;&lt;span&gt; dept_id &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 3&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new EmpExample();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;().andDeptIdEqualTo(&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;deleteByExample&lt;/span&gt;&lt;span&gt;(example);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 13&lt;/span&gt;&lt;span&gt;. 条件更新 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; UPDATE&lt;/span&gt;&lt;span&gt; emp &lt;/span&gt;&lt;span&gt;SET&lt;/span&gt;&lt;span&gt; salary &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 20000&lt;/span&gt;&lt;span&gt; WHERE&lt;/span&gt;&lt;span&gt; dept_id &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new EmpExample();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;().andDeptIdEqualTo(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;Emp record &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new Emp();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;record&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;setSalary&lt;/span&gt;&lt;span&gt;(new BigDecimal(&lt;/span&gt;&lt;span&gt;&quot;20000&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;updateByExampleSelective&lt;/span&gt;&lt;span&gt;(record, example);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;//&lt;/span&gt;&lt;span&gt; ======&lt;/span&gt;&lt;span&gt; 14&lt;/span&gt;&lt;span&gt;. 条件计数 &lt;/span&gt;&lt;span&gt;======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new EmpExample();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;().andGenderEqualTo(&lt;/span&gt;&lt;span&gt;&quot;M&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;long count &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;countByExample&lt;/span&gt;&lt;span&gt;(example);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Example 使用对照表&lt;a href=&quot;#example-使用对照表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;


























































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;需求&lt;/th&gt;&lt;th&gt;Example 方法&lt;/th&gt;&lt;th&gt;SQL 操作符&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;等于&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxEqualTo(value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;不等于&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxNotEqualTo(value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;大于&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxGreaterThan(value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;gt;&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;大于等于&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxGreaterThanOrEqualTo(value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;gt;=&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;小于&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxLessThan(value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;lt;&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;小于等于&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxLessThanOrEqualTo(value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;&amp;lt;=&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;模糊匹配&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxLike(value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;LIKE&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;非模糊匹配&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxNotLike(value)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;NOT LIKE&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;集合包含&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxIn(list)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;IN&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;集合不包含&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxNotIn(list)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;NOT IN&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;区间匹配&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxBetween(v1, v2)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;BETWEEN&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;为空&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxIsNull()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;IS NULL&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;非空&lt;/td&gt;&lt;td&gt;&lt;code&gt;andXxxIsNotNull()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;IS NOT NULL&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;添加 OR 条件组&lt;/td&gt;&lt;td&gt;&lt;code&gt;example.or().andXxx...()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;OR&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;排序&lt;/td&gt;&lt;td&gt;&lt;code&gt;example.setOrderByClause(&quot;xxx DESC&quot;)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;ORDER BY&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;去重&lt;/td&gt;&lt;td&gt;&lt;code&gt;example.setDistinct(true)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;DISTINCT&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;自定义 CommentGenerator（注释生成器）&lt;a href=&quot;#自定义-commentgenerator注释生成器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;默认注释的问题&lt;a href=&quot;#默认注释的问题&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MBG 默认生成的注释格式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * This field was generated by MyBatis Generator.&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * This field corresponds to the database column emp.emp_name&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * @mbg.generated&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;问题：注释无用、没有数据库字段注释、没有日期格式。&lt;/p&gt;
&lt;h3&gt;自定义 CommentGenerator&lt;a href=&quot;#自定义-commentgenerator&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.generator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.IntrospectedColumn;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.IntrospectedTable;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.dom.java.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.dom.xml.XmlElement;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.internal.DefaultCommentGenerator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.Properties;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * 自定义注释生成器&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * 生成数据库字段注释到 Java 实体类中&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; CustomCommentGenerator&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; DefaultCommentGenerator&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; addRemarkComments;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; addConfigurationProperties&lt;/span&gt;&lt;span&gt;(Properties &lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        super&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;addConfigurationProperties&lt;/span&gt;&lt;span&gt;(properties);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.addRemarkComments &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Boolean.&lt;/span&gt;&lt;span&gt;parseBoolean&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            properties.&lt;/span&gt;&lt;span&gt;getProperty&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;addRemarkComments&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 给字段添加注释（数据库列注释）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; addFieldComment&lt;/span&gt;&lt;span&gt;(Field &lt;/span&gt;&lt;span&gt;field&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                 IntrospectedTable &lt;/span&gt;&lt;span&gt;introspectedTable&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                 IntrospectedColumn &lt;/span&gt;&lt;span&gt;introspectedColumn&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (addRemarkComments) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            String remark &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; introspectedColumn.&lt;/span&gt;&lt;span&gt;getRemarks&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            if&lt;/span&gt;&lt;span&gt; (remark &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; !&lt;/span&gt;&lt;span&gt;remark.&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;isEmpty&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                field.&lt;/span&gt;&lt;span&gt;addJavaDocLine&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/**&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                field.&lt;/span&gt;&lt;span&gt;addJavaDocLine&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot; * &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; remark);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                field.&lt;/span&gt;&lt;span&gt;addJavaDocLine&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot; */&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 给类添加注释（表注释）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; addClassComment&lt;/span&gt;&lt;span&gt;(InnerClass &lt;/span&gt;&lt;span&gt;innerClass&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                 IntrospectedTable &lt;/span&gt;&lt;span&gt;introspectedTable&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String remark &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; introspectedTable.&lt;/span&gt;&lt;span&gt;getRemarks&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        innerClass.&lt;/span&gt;&lt;span&gt;addJavaDocLine&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/**&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (remark &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; !&lt;/span&gt;&lt;span&gt;remark.&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;isEmpty&lt;/span&gt;&lt;span&gt;()) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            innerClass.&lt;/span&gt;&lt;span&gt;addJavaDocLine&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot; * &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; remark);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        innerClass.&lt;/span&gt;&lt;span&gt;addJavaDocLine&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot; * 对应数据库表: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            introspectedTable.&lt;/span&gt;&lt;span&gt;getFullyQualifiedTable&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        innerClass.&lt;/span&gt;&lt;span&gt;addJavaDocLine&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot; */&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 给 getter 方法添加注释&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; addGetterComment&lt;/span&gt;&lt;span&gt;(Method &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                  IntrospectedTable &lt;/span&gt;&lt;span&gt;introspectedTable&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                  IntrospectedColumn &lt;/span&gt;&lt;span&gt;introspectedColumn&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 不生成 getter 注释（保持简洁）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 给 setter 方法添加注释&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; addSetterComment&lt;/span&gt;&lt;span&gt;(Method &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                  IntrospectedTable &lt;/span&gt;&lt;span&gt;introspectedTable&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                  IntrospectedColumn &lt;/span&gt;&lt;span&gt;introspectedColumn&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 不生成 setter 注释（保持简洁）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;在配置文件中使用自定义注释生成器&lt;a href=&quot;#在配置文件中使用自定义注释生成器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mysqlContext&quot;&lt;/span&gt;&lt;span&gt; targetRuntime&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MyBatis3&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 使用自定义注释生成器 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.generator.CustomCommentGenerator&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;suppressAllComments&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;suppressDate&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;addRemarkComments&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- ... 其他配置 ... --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;生成的实体类效果&lt;a href=&quot;#生成的实体类效果&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  * 员工表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  * 对应数据库表: mybatis_demo.emp&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      * 员工ID&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 员工姓名&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 性别 M-男 F-女&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String gender;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // ... getter/setter&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;自定义 Plugin 插件&lt;a href=&quot;#自定义-plugin-插件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Plugin 机制概述&lt;a href=&quot;#plugin-机制概述&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MBG 通过 &lt;strong&gt;Plugin 插件机制&lt;/strong&gt; 实现代码生成过程的扩展。插件可以拦截生成过程，修改或增加生成的代码。&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; MBG 生成流程&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     ↓&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ┌─────────────────────────────────┐&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  阶段1: Model Class 生成         │ ← Plugin 可拦截&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├─────────────────────────────────┤&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  阶段2: SQL Map (XML) 生成       │ ← Plugin 可拦截&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├─────────────────────────────────┤&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │  阶段3: Client (Mapper) 生成     │ ← Plugin 可拦截&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├─────────────────────────────────┤&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│  阶段4: Example Class 生成       │ ← Plugin 可拦截&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└─────────────────────────────────┘&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;内置插件列表&lt;a href=&quot;#内置插件列表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;插件类&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;功能&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;SerializablePlugin&lt;/td&gt;&lt;td&gt;让实体类实现 Serializable 接口&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ToStringPlugin&lt;/td&gt;&lt;td&gt;生成 toString() 方法&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;EqualsAndHashCodePlugin&lt;/td&gt;&lt;td&gt;生成 equals() 和 hashCode() 方法&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;RowBoundsPlugin&lt;/td&gt;&lt;td&gt;生成分页方法（基于 RowBounds，不推荐 MySQL 使用）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VirtualKeyPlugin&lt;/td&gt;&lt;td&gt;虚拟主键插件&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;FluentBuilderMethodsPlugin&lt;/td&gt;&lt;td&gt;生成链式 setter（返回 this）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MapperNamePlugin&lt;/td&gt;&lt;td&gt;自定义 Mapper 名称&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;RenameExampleClassPlugin&lt;/td&gt;&lt;td&gt;重命名 Example 类&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CaseInsensitiveLikePlugin&lt;/td&gt;&lt;td&gt;大小写不敏感 LIKE 查询&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;UnmergeableXmlMapperPlugin&lt;/td&gt;&lt;td&gt;XML 不合并，直接覆盖&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;自定义 Plugin 示例：Lombok 插件&lt;a href=&quot;#自定义-plugin-示例lombok-插件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;让生成的实体类使用 Lombok 注解，替代冗长的 getter/setter：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.generator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.IntrospectedTable;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.PluginAdapter;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.dom.java.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * 自定义 Lombok 插件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * 让生成的实体类使用 @Data 注解，去掉 getter/setter&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; LombokPlugin&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; PluginAdapter&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; validate&lt;/span&gt;&lt;span&gt;(List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;warnings&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 给实体类添加 Lombok 注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; modelBaseRecordClassGenerated&lt;/span&gt;&lt;span&gt;(TopLevelClass &lt;/span&gt;&lt;span&gt;topLevelClass&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                                  IntrospectedTable &lt;/span&gt;&lt;span&gt;introspectedTable&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 添加 @Data 注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        topLevelClass.&lt;/span&gt;&lt;span&gt;addImportedType&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;lombok.Data&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        topLevelClass.&lt;/span&gt;&lt;span&gt;addAnnotation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;@Data&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 添加 @Builder 注解（可选）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        topLevelClass.&lt;/span&gt;&lt;span&gt;addImportedType&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;lombok.Builder&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        topLevelClass.&lt;/span&gt;&lt;span&gt;addAnnotation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;@Builder&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 添加 @NoArgsConstructor&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        topLevelClass.&lt;/span&gt;&lt;span&gt;addImportedType&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;lombok.NoArgsConstructor&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        topLevelClass.&lt;/span&gt;&lt;span&gt;addAnnotation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;@NoArgsConstructor&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 添加 @AllArgsConstructor&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        topLevelClass.&lt;/span&gt;&lt;span&gt;addImportedType&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;lombok.AllArgsConstructor&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        topLevelClass.&lt;/span&gt;&lt;span&gt;addAnnotation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;@AllArgsConstructor&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 给主键类添加 Lombok 注解（如果有）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; modelPrimaryKeyClassGenerated&lt;/span&gt;&lt;span&gt;(TopLevelClass &lt;/span&gt;&lt;span&gt;topLevelClass&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                                  IntrospectedTable &lt;/span&gt;&lt;span&gt;introspectedTable&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        topLevelClass.&lt;/span&gt;&lt;span&gt;addImportedType&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;lombok.Data&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        topLevelClass.&lt;/span&gt;&lt;span&gt;addAnnotation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;@Data&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 禁止生成 getter 方法（由 Lombok @Data 提供）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; modelGetterMethodGenerated&lt;/span&gt;&lt;span&gt;(Method &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                               TopLevelClass &lt;/span&gt;&lt;span&gt;topLevelClass&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                               IntrospectedColumn &lt;/span&gt;&lt;span&gt;introspectedColumn&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                               IntrospectedTable &lt;/span&gt;&lt;span&gt;introspectedTable&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                               ModelClassType &lt;/span&gt;&lt;span&gt;modelClassType&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;;  &lt;/span&gt;&lt;span&gt;// false = 不生成 getter&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 禁止生成 setter 方法&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; modelSetterMethodGenerated&lt;/span&gt;&lt;span&gt;(Method &lt;/span&gt;&lt;span&gt;method&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                               TopLevelClass &lt;/span&gt;&lt;span&gt;topLevelClass&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                               IntrospectedColumn &lt;/span&gt;&lt;span&gt;introspectedColumn&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                               IntrospectedTable &lt;/span&gt;&lt;span&gt;introspectedTable&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                               ModelClassType &lt;/span&gt;&lt;span&gt;modelClassType&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;;  &lt;/span&gt;&lt;span&gt;// false = 不生成 setter&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;配置中使用自定义插件&lt;a href=&quot;#配置中使用自定义插件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mysqlContext&quot;&lt;/span&gt;&lt;span&gt; targetRuntime&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MyBatis3&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- 内置插件 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.SerializablePlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.EqualsAndHashCodePlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- ★ 自定义 Lombok 插件 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.generator.LombokPlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- ★ 重命名 Example 类为 Query --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.RenameExampleClassPlugin&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;searchString&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Example$&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;replaceString&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Query&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 自定义注释生成器 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.generator.CustomCommentGenerator&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;suppressAllComments&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;addRemarkComments&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- ... 其他配置 ... --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;自定义 Plugin 示例：Mapper 继承通用接口&lt;a href=&quot;#自定义-plugin-示例mapper-继承通用接口&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.example.generator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.IntrospectedTable;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.PluginAdapter;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.dom.java.Interface;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.dom.java.TopLevelClass;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * 让所有生成的 Mapper 接口继承自定义的 BaseMapper&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; BaseMapperPlugin&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; PluginAdapter&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String baseMapperPackage;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; validate&lt;/span&gt;&lt;span&gt;(List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;warnings&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        baseMapperPackage &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; properties.&lt;/span&gt;&lt;span&gt;getProperty&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;baseMapperPackage&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; baseMapperPackage &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; !&lt;/span&gt;&lt;span&gt;baseMapperPackage.&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;isEmpty&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; clientGenerated&lt;/span&gt;&lt;span&gt;(Interface &lt;/span&gt;&lt;span&gt;interfaze&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                    TopLevelClass &lt;/span&gt;&lt;span&gt;topLevelClass&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                    IntrospectedTable &lt;/span&gt;&lt;span&gt;introspectedTable&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 导入 BaseMapper&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        FullyQualifiedJavaType baseMapperType &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            new&lt;/span&gt;&lt;span&gt; FullyQualifiedJavaType&lt;/span&gt;&lt;span&gt;(baseMapperPackage);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        interfaze.&lt;/span&gt;&lt;span&gt;addImportedType&lt;/span&gt;&lt;span&gt;(baseMapperType);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 让 Mapper 继承 BaseMapper&amp;lt;实体类&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        FullyQualifiedJavaType entityType &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            new&lt;/span&gt;&lt;span&gt; FullyQualifiedJavaType&lt;/span&gt;&lt;span&gt;(introspectedTable.&lt;/span&gt;&lt;span&gt;getBaseRecordType&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        interfaze.&lt;/span&gt;&lt;span&gt;addSuperInterface&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            new&lt;/span&gt;&lt;span&gt; FullyQualifiedJavaType&lt;/span&gt;&lt;span&gt;(baseMapperPackage &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;&amp;lt;&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     entityType.&lt;/span&gt;&lt;span&gt;getShortName&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;&amp;gt;&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;plugin type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.generator.BaseMapperPlugin&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;property name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;baseMapperPackage&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper.BaseMapper&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;MyBatis-Plus 代码生成器（3.5.x+）&lt;a href=&quot;#mybatis-plus-代码生成器35x&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;MP Generator 概述&lt;a href=&quot;#mp-generator-概述&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MyBatis-Plus 代码生成器比 MBG 功能更强大，能生成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Entity 实体类（支持 Lombok / Swagger 注解）&lt;/li&gt;
&lt;li&gt;Mapper 接口（继承 BaseMapper）&lt;/li&gt;
&lt;li&gt;Mapper XML 映射文件&lt;/li&gt;
&lt;li&gt;Service 接口 + Service 实现类&lt;/li&gt;
&lt;li&gt;Controller 控制器（含 RESTful 接口）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;依赖配置&lt;a href=&quot;#依赖配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- MyBatis-Plus（包含 MyBatis） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.baomidou&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-plus-boot-starter&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.5.7&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- MP 代码生成器核心 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.baomidou&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-plus-generator&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.5.7&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- 模板引擎（Freemarker / Velocity / Beetl 任选其一） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.freemarker&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;freemarker&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;2.3.32&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- MySQL 驱动 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;8.0.33&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- Lombok（可选） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.projectlombok&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;lombok&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.18.34&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;provided&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- Swagger / SpringDoc（可选） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springdoc&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;springdoc-openapi-starter-webmvc-ui&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;2.5.0&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;快速生成器（FastAutoGenerator）&lt;a href=&quot;#快速生成器fastautogenerator&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MyBatis-Plus 3.5.3+ 提供了 FastAutoGenerator，链式配置一行搞定：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.generator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.generator.FastAutoGenerator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.generator.config.OutputFile;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.Collections;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MpGenerator&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        FastAutoGenerator.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;jdbc:mysql://localhost:3306/mybatis_demo?&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     useSSL=false&amp;amp;serverTimezone=Asia/Shanghai&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;root&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;123456&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            // ====== 全局配置 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            .&lt;/span&gt;&lt;span&gt;globalConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                builder.&lt;/span&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;example&quot;&lt;/span&gt;&lt;span&gt;)               &lt;/span&gt;&lt;span&gt;// 作者&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;outputDir&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;src/main/java&quot;&lt;/span&gt;&lt;span&gt;)      &lt;/span&gt;&lt;span&gt;// 输出目录&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;enableSwagger&lt;/span&gt;&lt;span&gt;()                  &lt;/span&gt;&lt;span&gt;// 开启 Swagger 注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;commentDate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;yyyy-MM-dd&quot;&lt;/span&gt;&lt;span&gt;);       &lt;/span&gt;&lt;span&gt;// 注释日期格式&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            // ====== 包配置 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            .&lt;/span&gt;&lt;span&gt;packageConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                builder.&lt;/span&gt;&lt;span&gt;parent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example&quot;&lt;/span&gt;&lt;span&gt;)           &lt;/span&gt;&lt;span&gt;// 父包名&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;entity&quot;&lt;/span&gt;&lt;span&gt;)                &lt;/span&gt;&lt;span&gt;// 实体类包名&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;mapper&quot;&lt;/span&gt;&lt;span&gt;)                &lt;/span&gt;&lt;span&gt;// Mapper 包名&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;service&quot;&lt;/span&gt;&lt;span&gt;)              &lt;/span&gt;&lt;span&gt;// Service 包名&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;serviceImpl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;service.impl&quot;&lt;/span&gt;&lt;span&gt;)     &lt;/span&gt;&lt;span&gt;// Service 实现包名&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;controller&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;controller&quot;&lt;/span&gt;&lt;span&gt;)        &lt;/span&gt;&lt;span&gt;// Controller 包名&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;mapper&quot;&lt;/span&gt;&lt;span&gt;)                   &lt;/span&gt;&lt;span&gt;// XML 资源路径&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;pathInfo&lt;/span&gt;&lt;span&gt;(Collections.&lt;/span&gt;&lt;span&gt;singletonMap&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                           OutputFile.xml,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                           &quot;src/main/resources/mapper&quot;&lt;/span&gt;&lt;span&gt;)); &lt;/span&gt;&lt;span&gt;// XML 输出目录&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            // ====== 策略配置 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            .&lt;/span&gt;&lt;span&gt;strategyConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                builder.&lt;/span&gt;&lt;span&gt;addInclude&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;dept&quot;&lt;/span&gt;&lt;span&gt;)       &lt;/span&gt;&lt;span&gt;// 表名（可变参数）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;addTablePrefix&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;t_&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;sys_&quot;&lt;/span&gt;&lt;span&gt;)    &lt;/span&gt;&lt;span&gt;// 过滤表前缀&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;entityBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;naming&lt;/span&gt;&lt;span&gt;(NamingStrategy.underline_to_camel)  &lt;/span&gt;&lt;span&gt;// 下划线转驼峰&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;columnNaming&lt;/span&gt;&lt;span&gt;(NamingStrategy.underline_to_camel)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;enableLombok&lt;/span&gt;&lt;span&gt;()                   &lt;/span&gt;&lt;span&gt;// 使用 Lombok&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;enableTableFieldAnnotation&lt;/span&gt;&lt;span&gt;()     &lt;/span&gt;&lt;span&gt;// 生成字段注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;logicDeleteColumnName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;deleted&quot;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;// 逻辑删除字段&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;versionColumnName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;version&quot;&lt;/span&gt;&lt;span&gt;)     &lt;/span&gt;&lt;span&gt;// 乐观锁字段&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;idType&lt;/span&gt;&lt;span&gt;(IdType.AUTO)              &lt;/span&gt;&lt;span&gt;// 主键策略&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;formatFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%s&quot;&lt;/span&gt;&lt;span&gt;)             &lt;/span&gt;&lt;span&gt;// 实体类名格式&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;mapperBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;enableMapperAnnotation&lt;/span&gt;&lt;span&gt;()          &lt;/span&gt;&lt;span&gt;// 生成 @Mapper 注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;formatMapperFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sMapper&quot;&lt;/span&gt;&lt;span&gt;)   &lt;/span&gt;&lt;span&gt;// Mapper 文件名格式&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;formatXmlFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sMapper&quot;&lt;/span&gt;&lt;span&gt;)      &lt;/span&gt;&lt;span&gt;// XML 文件名格式&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;serviceBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;formatServiceFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sService&quot;&lt;/span&gt;&lt;span&gt;)     &lt;/span&gt;&lt;span&gt;// Service 接口名&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;formatServiceImplFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sServiceImpl&quot;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;// Service 实现名&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;controllerBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                       .&lt;/span&gt;&lt;span&gt;enableRestStyle&lt;/span&gt;&lt;span&gt;();                &lt;/span&gt;&lt;span&gt;// 生成 @RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            // ====== 模板引擎 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            .&lt;/span&gt;&lt;span&gt;templateEngine&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; FreemarkerTemplateEngine&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            // ====== 执行 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            .&lt;/span&gt;&lt;span&gt;execute&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;✅ MyBatis-Plus 代码生成完成！&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;生成的目录结构&lt;a href=&quot;#生成的目录结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; src/main/java/com/example/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├── entity/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   ├── Emp.java              ← @Data + @TableName + 字段注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   └── Dept.java&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├── mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   ├── EmpMapper.java        ← extends BaseMapper&amp;lt;Emp&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   └── DeptMapper.java&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├── service/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   ├── EmpService.java       ← extends IService&amp;lt;Emp&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── impl/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│       └── EmpServiceImpl.java  ← extends ServiceImpl&amp;lt;EmpMapper, Emp&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└── controller/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ├── EmpController.java    ← @RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    └── DeptController.java&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;src/main/resources/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└── mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ├── EmpMapper.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    └── DeptMapper.xml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;MyBatis-Plus Generator 配置详解&lt;a href=&quot;#mybatis-plus-generator-配置详解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;完整 AutoGenerator 配置（非 Fast 模式）&lt;a href=&quot;#完整-autogenerator-配置非-fast-模式&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; com.example.generator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.annotation.IdType;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.generator.AutoGenerator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.generator.config.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MpFullGenerator&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // ====== 1. 数据源配置 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        DataSourceConfig dataSourceConfig &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; DataSourceConfig.&lt;/span&gt;&lt;span&gt;builder&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;jdbc:mysql://localhost:3306/mybatis_demo?&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     useSSL=false&amp;amp;serverTimezone=Asia/Shanghai&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;com.mysql.cj.jdbc.Driver&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;root&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &quot;123456&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            .&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // ====== 2. 全局配置 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        GlobalConfig globalConfig &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; GlobalConfig.&lt;/span&gt;&lt;span&gt;builder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;example&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;outputDir&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;src/main/java&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;enableSwagger&lt;/span&gt;&lt;span&gt;()                    &lt;/span&gt;&lt;span&gt;// Swagger 注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;disableOpenDir&lt;/span&gt;&lt;span&gt;()                    &lt;/span&gt;&lt;span&gt;// 生成后不自动打开目录&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;commentDate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;yyyy-MM-dd&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;dateType&lt;/span&gt;&lt;span&gt;(DateType.TIME_PACK)        &lt;/span&gt;&lt;span&gt;// 使用 java.time 包&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // ====== 3. 包配置 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        PackageConfig packageConfig &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; PackageConfig.&lt;/span&gt;&lt;span&gt;builder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;parent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;moduleName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;system&quot;&lt;/span&gt;&lt;span&gt;)               &lt;/span&gt;&lt;span&gt;// 模块名（会加到包路径中）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;entity&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;mapper&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;service&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;serviceImpl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;service.impl&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;controller&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;controller&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;mapper.xml&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;pathInfo&lt;/span&gt;&lt;span&gt;(java.util.Collections.&lt;/span&gt;&lt;span&gt;singletonMap&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    OutputFile.xml,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &quot;src/main/resources/mapper&quot;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // ====== 4. 模板配置 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        TemplateConfig templateConfig &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; TemplateConfig.&lt;/span&gt;&lt;span&gt;builder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;templates/entity.java&quot;&lt;/span&gt;&lt;span&gt;)    &lt;/span&gt;&lt;span&gt;// 使用自定义模板&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;templates/mapper.java&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;templates/mapper.xml&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;templates/service.java&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;serviceImpl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;templates/serviceImpl.java&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;controller&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;templates/controller.java&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // ====== 5. 策略配置 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         StrategyConfig strategyConfig &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; StrategyConfig.&lt;/span&gt;&lt;span&gt;builder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;addInclude&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;dept&quot;&lt;/span&gt;&lt;span&gt;)          &lt;/span&gt;&lt;span&gt;// 要生成的表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;addTablePrefix&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;t_&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;sys_&quot;&lt;/span&gt;&lt;span&gt;)       &lt;/span&gt;&lt;span&gt;// 过滤表前缀&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;addTableSuffix&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;_tab&quot;&lt;/span&gt;&lt;span&gt;)             &lt;/span&gt;&lt;span&gt;// 过滤表后缀&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 // 实体策略&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;entityBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;naming&lt;/span&gt;&lt;span&gt;(NamingStrategy.underline_to_camel)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;columnNaming&lt;/span&gt;&lt;span&gt;(NamingStrategy.underline_to_camel)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;enableLombok&lt;/span&gt;&lt;span&gt;()                     &lt;/span&gt;&lt;span&gt;// Lombok 注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;enableTableFieldAnnotation&lt;/span&gt;&lt;span&gt;()       &lt;/span&gt;&lt;span&gt;// @TableField 注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;enableActiveRecord&lt;/span&gt;&lt;span&gt;()               &lt;/span&gt;&lt;span&gt;// ActiveRecord 模式&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;enableFileOverride&lt;/span&gt;&lt;span&gt;()               &lt;/span&gt;&lt;span&gt;// 覆盖已有文件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;logicDeleteColumnName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;deleted&quot;&lt;/span&gt;&lt;span&gt;)   &lt;/span&gt;&lt;span&gt;// 逻辑删除&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;versionColumnName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;version&quot;&lt;/span&gt;&lt;span&gt;)       &lt;/span&gt;&lt;span&gt;// 乐观锁&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;idType&lt;/span&gt;&lt;span&gt;(IdType.AUTO)                &lt;/span&gt;&lt;span&gt;// 主键策略&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;formatFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%s&quot;&lt;/span&gt;&lt;span&gt;)               &lt;/span&gt;&lt;span&gt;// 实体类名格式&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;superClass&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example.BaseEntity&quot;&lt;/span&gt;&lt;span&gt;)  &lt;/span&gt;&lt;span&gt;// 父类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 // Mapper 策略&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;mapperBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;enableMapperAnnotation&lt;/span&gt;&lt;span&gt;()           &lt;/span&gt;&lt;span&gt;// @Mapper 注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;enableBaseResultMap&lt;/span&gt;&lt;span&gt;()              &lt;/span&gt;&lt;span&gt;// 生成 BaseResultMap&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;enableBaseColumnList&lt;/span&gt;&lt;span&gt;()             &lt;/span&gt;&lt;span&gt;// 生成 BaseColumnList&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;formatMapperFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sMapper&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;formatXmlFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sMapper&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 // Service 策略&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;serviceBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;formatServiceFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sService&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;formatServiceImplFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sServiceImpl&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;superServiceClass&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example.BaseService&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;superServiceImplClass&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example.BaseServiceImpl&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 // Controller 策略&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;controllerBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;enableRestStyle&lt;/span&gt;&lt;span&gt;()                  &lt;/span&gt;&lt;span&gt;// @RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;enableHyphenStyle&lt;/span&gt;&lt;span&gt;()                &lt;/span&gt;&lt;span&gt;// URL 连字符风格&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;formatFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sController&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         // ====== 6. 注入配置（自定义变量） ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         InjectionConfig injectionConfig &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; InjectionConfig.&lt;/span&gt;&lt;span&gt;builder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;customMap&lt;/span&gt;&lt;span&gt;(java.util.Map.&lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                     &quot;author&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;example&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                     &quot;version&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;1.0.0&quot;&lt;/span&gt;&lt;span&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // ====== 7. 组装执行 ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        AutoGenerator generator &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; AutoGenerator&lt;/span&gt;&lt;span&gt;(dataSourceConfig);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        generator.&lt;/span&gt;&lt;span&gt;global&lt;/span&gt;&lt;span&gt;(globalConfig);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        generator.&lt;/span&gt;&lt;span&gt;packageInfo&lt;/span&gt;&lt;span&gt;(packageConfig);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        generator.&lt;/span&gt;&lt;span&gt;template&lt;/span&gt;&lt;span&gt;(templateConfig);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        generator.&lt;/span&gt;&lt;span&gt;strategy&lt;/span&gt;&lt;span&gt;(strategyConfig);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        generator.&lt;/span&gt;&lt;span&gt;injection&lt;/span&gt;&lt;span&gt;(injectionConfig);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        generator.&lt;/span&gt;&lt;span&gt;templateEngine&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; FreemarkerTemplateEngine&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        generator.&lt;/span&gt;&lt;span&gt;execute&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;✅ 代码生成完成！&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;IdType 主键策略&lt;a href=&quot;#idtype-主键策略&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;code&gt;IdType&lt;/code&gt; 值&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;th&gt;常见场景&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;AUTO&lt;/code&gt;&lt;/td&gt;&lt;td&gt;使用数据库自增主键&lt;/td&gt;&lt;td&gt;MySQL &lt;code&gt;AUTO_INCREMENT&lt;/code&gt; 等&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;NONE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;不指定局部策略，按全局配置处理&lt;/td&gt;&lt;td&gt;由项目统一配置&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;INPUT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;插入前由开发者手动赋值&lt;/td&gt;&lt;td&gt;业务主键&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ASSIGN_ID&lt;/code&gt;&lt;/td&gt;&lt;td&gt;使用默认标识符生成器分配长整型 ID&lt;/td&gt;&lt;td&gt;分布式系统常用&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;ASSIGN_UUID&lt;/code&gt;&lt;/td&gt;&lt;td&gt;分配不带连字符的 UUID 字符串&lt;/td&gt;&lt;td&gt;字符串主键&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;NamingStrategy 命名策略&lt;a href=&quot;#namingstrategy-命名策略&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;值&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;th&gt;示例&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;underline_to_camel&lt;/code&gt;&lt;/td&gt;&lt;td&gt;下划线命名转驼峰命名&lt;/td&gt;&lt;td&gt;&lt;code&gt;emp_name&lt;/code&gt; 转为 &lt;code&gt;empName&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;no_change&lt;/code&gt;&lt;/td&gt;&lt;td&gt;保持数据库名称不变&lt;/td&gt;&lt;td&gt;&lt;code&gt;emp_name&lt;/code&gt; 保持为 &lt;code&gt;emp_name&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;数据源类型映射配置&lt;a href=&quot;#数据源类型映射配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; // MySQL 8.x 类型映射自定义&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; DataSourceConfig dataSourceConfig &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; DataSourceConfig.&lt;/span&gt;&lt;span&gt;builder&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         url, driver, username, password)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     .&lt;/span&gt;&lt;span&gt;typeConvert&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; ITypeConvert&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         public&lt;/span&gt;&lt;span&gt; IColumnType &lt;/span&gt;&lt;span&gt;executeTypeConvert&lt;/span&gt;&lt;span&gt;(TableInfo &lt;/span&gt;&lt;span&gt;tableInfo&lt;/span&gt;&lt;span&gt;, String &lt;/span&gt;&lt;span&gt;fieldName&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     String &lt;/span&gt;&lt;span&gt;fieldType&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             // 自定义类型映射&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;&quot;tinyint(1)&quot;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;equalsIgnoreCase&lt;/span&gt;&lt;span&gt;(fieldType)) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 return&lt;/span&gt;&lt;span&gt; DbColumnType.BOOLEAN;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;&quot;json&quot;&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;equalsIgnoreCase&lt;/span&gt;&lt;span&gt;(fieldType)) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                return&lt;/span&gt;&lt;span&gt; DbColumnType.OBJECT;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            // 默认使用 MP 内置映射&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            return&lt;/span&gt;&lt;span&gt; TypeConverts.&lt;/span&gt;&lt;span&gt;useDefault&lt;/span&gt;&lt;span&gt;(tableInfo, fieldName, fieldType);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;模板自定义&lt;a href=&quot;#模板自定义&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;自定义实体类模板&lt;a href=&quot;#自定义实体类模板&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;MP 使用 Freemarker 模板引擎，默认模板位于 mybatis-plus-generator jar 包中的 templates/ 目录。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;自定义 entity.java.ftl 模板：&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; ${&lt;/span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;E&lt;/span&gt;&lt;span&gt;ntity};&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;#list table.importPackages as pkg&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; ${pkg};&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;#list&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; swagger2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.annotations.media.Schema;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; entityLombokAnnotations&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; lombok.Data;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; lombok.experimental.Accessors;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * &amp;lt;p&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * ${table.comment!}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * &amp;lt;/p&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * &lt;/span&gt;&lt;span&gt;@author&lt;/span&gt;&lt;span&gt; ${author}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * &lt;/span&gt;&lt;span&gt;@since&lt;/span&gt;&lt;span&gt; ${date}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; entityLombokAnnotations&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Accessors&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;chain&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; swagger2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;${table.comment!}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;TableName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;${schemaName}${table.name}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; $&lt;/span&gt;&lt;span&gt;{entity} implements Serializable {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; long&lt;/span&gt;&lt;span&gt; serialVersionUID &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 1L&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt; ----------&lt;/span&gt;&lt;span&gt;  BEGIN 字段循环遍历  &lt;/span&gt;&lt;span&gt;----------&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;#list table.fields as field&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; field.keyFlag&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; field.keyIdentityFlag&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;${field.annotationColumnName}&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; IdType.AUTO)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;#elseif idType&lt;/span&gt;&lt;span&gt;??&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;${field.annotationColumnName}&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; IdType.${idType})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;else&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;${field.annotationColumnName}&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; IdType.ASSIGN_ID)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;#elseif field.fill&lt;/span&gt;&lt;span&gt;??&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;--&lt;/span&gt;&lt;span&gt; 通用填充字段 &lt;/span&gt;&lt;span&gt;--&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;${field.annotationColumnName}&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;fill&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     FieldFill.${field.fill})&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;#elseif &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;field.propertyType&lt;/span&gt;&lt;span&gt;?&lt;/span&gt;&lt;span&gt;ends_with&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;Serializable&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;${field.annotationColumnName}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; swagger2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;${field.comment!}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; ${field.propertyType} ${field.propertyName};&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;#list&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;------------&lt;/span&gt;&lt;span&gt;  END 字段循环遍历  &lt;/span&gt;&lt;span&gt;----------&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; !&lt;/span&gt;&lt;span&gt;entityLombokAnnotations&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;#list table.fields as field&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; field.propertyType &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &quot;boolean&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;#assign getprefix&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;is&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;else&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;#assign getprefix&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;get&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; ${field.propertyType} ${getprefix}${field.capitalPropertyName}() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; ${field.propertyName};&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; set${field.capitalPropertyName}(${field.propertyType}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     ${field.propertyName}) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.${field.propertyName} &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; ${field.propertyName};&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;#list&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;使用自定义模板&lt;a href=&quot;#使用自定义模板&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;TemplateConfig templateConfig &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; TemplateConfig.&lt;/span&gt;&lt;span&gt;builder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/templates/my-entity.java&quot;&lt;/span&gt;&lt;span&gt;)    &lt;/span&gt;&lt;span&gt;// 自定义模板路径&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/templates/my-mapper.java&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/templates/my-mapper.xml&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/templates/my-service.java&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;serviceImpl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/templates/my-serviceImpl.java&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;controller&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/templates/my-controller.java&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;将自定义模板放在 src/main/resources/templates/ 目录下。&lt;/p&gt;
&lt;h3&gt;自定义 Controller 模板（RESTful 风格）&lt;a href=&quot;#自定义-controller-模板restful-风格&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; ${&lt;/span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;C&lt;/span&gt;&lt;span&gt;ontroller};&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; ${&lt;/span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt;.Entity}.${entity};&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; ${&lt;/span&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt;.Service}.${entity}Service;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; swagger2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.annotations.tags.Tag;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.annotations.Operation;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;/&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.springframework.beans.factory.annotation.Autowired;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * &amp;lt;p&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * ${table.comment!} 前端控制器&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * &amp;lt;/p&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; *&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * &lt;/span&gt;&lt;span&gt;@author&lt;/span&gt;&lt;span&gt; ${author}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * &lt;/span&gt;&lt;span&gt;@since&lt;/span&gt;&lt;span&gt; ${date}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; swagger2&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Tag&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;${table.comment!}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;#&lt;/span&gt;&lt;span&gt;if&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequestMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/${table.entityPath}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; $&lt;/span&gt;&lt;span&gt;{entity}Controller {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Autowired&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; ${entity}Service ${table.entityPath}Service;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;查询所有&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; List&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;${entity}&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;span&gt; list&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; ${table.entityPath}Service.&lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;根据ID查询&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/{id}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; ${entity} &lt;/span&gt;&lt;span&gt;getById&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;PathVariable&lt;/span&gt;&lt;span&gt; ${entity} ${table.entityPath}) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; ${table.entityPath}Service.&lt;/span&gt;&lt;span&gt;getById&lt;/span&gt;&lt;span&gt;(${table.entityPath});&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;新增&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PostMapping&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; save&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;RequestBody&lt;/span&gt;&lt;span&gt; ${entity} ${table.entityPath}) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; ${table.entityPath}Service.&lt;/span&gt;&lt;span&gt;save&lt;/span&gt;&lt;span&gt;(${table.entityPath});&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;修改&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PutMapping&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; update&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;RequestBody&lt;/span&gt;&lt;span&gt; ${entity} ${table.entityPath}) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; ${table.entityPath}Service.&lt;/span&gt;&lt;span&gt;updateById&lt;/span&gt;&lt;span&gt;(${table.entityPath});&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;根据ID删除&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;DeleteMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/{id}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; delete&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;PathVariable&lt;/span&gt;&lt;span&gt; ${entity} ${table.entityPath}) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; ${table.entityPath}Service.&lt;/span&gt;&lt;span&gt;removeById&lt;/span&gt;&lt;span&gt;(${table.entityPath});&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Spring Boot 集成逆向工程&lt;a href=&quot;#spring-boot-集成逆向工程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Spring Boot 项目中集成 MBG&lt;a href=&quot;#spring-boot-项目中集成-mbg&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;pom.xml 配置：&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- Spring Boot Starter --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-web&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- MyBatis Spring Boot Starter --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis.spring.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-spring-boot-starter&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.0.3&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;!-- MySQL --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;runtime&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-maven-plugin&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- MBG 插件 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis.generator&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-generator-maven-plugin&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.4.2&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;executions&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;!-- 可选：绑定到 generate-sources 阶段自动执行 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;execution&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;&amp;gt;Generate MyBatis Artifacts&amp;lt;/&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;&lt;/span&gt;&lt;span&gt;goals&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        &amp;lt;&lt;/span&gt;&lt;span&gt;goal&lt;/span&gt;&lt;span&gt;&amp;gt;generate&amp;lt;/&lt;/span&gt;&lt;span&gt;goal&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;/&lt;/span&gt;&lt;span&gt;goals&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;!-- 取消注释则每次构建自动生成 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;!-- &amp;lt;phase&amp;gt;generate-sources&amp;lt;/phase&amp;gt; --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;/&lt;/span&gt;&lt;span&gt;execution&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;executions&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;configurationFile&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    src/main/resources/generator/generatorConfig.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;/&lt;/span&gt;&lt;span&gt;configurationFile&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;overwrite&lt;/span&gt;&lt;span&gt;&amp;gt;true&amp;lt;/&lt;/span&gt;&lt;span&gt;overwrite&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;verbose&lt;/span&gt;&lt;span&gt;&amp;gt;true&amp;lt;/&lt;/span&gt;&lt;span&gt;verbose&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;8.0.33&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;plugins&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Spring Boot + MyBatis-Plus 集成&lt;a href=&quot;#spring-boot--mybatis-plus-集成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;pom.xml:&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-web&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.baomidou&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-plus-spring-boot3-starter&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.5.7&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.baomidou&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-plus-generator&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.5.7&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.freemarker&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;freemarker&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;runtime&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.projectlombok&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;lombok&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;gt;true&amp;lt;/&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;application.yml:&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; spring&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;   datasource&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     url&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;jdbc:mysql://localhost:3306/mybatis_demo?&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     useSSL=false&amp;amp;serverTimezone=Asia/Shanghai&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     username&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;root&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     password&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;123456&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     driver-class-name&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;com.mysql.cj.jdbc.Driver&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; mybatis-plus&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;   mapper-locations&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;classpath:mapper/*.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  type-aliases-package&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;com.example.entity&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  configuration&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    map-underscore-to-camel-case&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    log-impl&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;org.apache.ibatis.logging.stdout.StdOutImpl&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;  global-config&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    db-config&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      id-type&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;auto&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      logic-delete-field&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;deleted&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      logic-delete-value&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;      logic-not-delete-value&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;生成的实体类使用示例&lt;a href=&quot;#生成的实体类使用示例&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; // ====== Emp.java（MP 生成的实体类）======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;员工表&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;TableName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Accessors&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;chain&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; Serializable&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; long&lt;/span&gt;&lt;span&gt; serialVersionUID &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 1L&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;员工ID&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;emp_id&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;type&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; IdType.AUTO)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;员工姓名&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;性别 M-男 F-女&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String gender;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;邮箱&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String email;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;工资&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; BigDecimal salary;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;所属部门ID&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;dept_id&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer deptId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;入职日期&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDate hireDate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;创建时间&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;fill&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; FieldFill.INSERT)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDateTime createTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;更新时间&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;TableField&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;fill&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; FieldFill.INSERT_UPDATE)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDateTime updateTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// ====== EmpMapper.java ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Mapper&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; EmpMapper&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; BaseMapper&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // BaseMapper 已提供 insert/delete/update/select 等方法&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 可以在这里添加自定义 SQL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// ====== EmpService.java ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; interface&lt;/span&gt;&lt;span&gt; EmpService&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; IService&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // IService 已提供通用业务方法&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 可以在这里添加自定义业务方法&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// ====== EmpServiceImpl.java ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; EmpServiceImpl&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; ServiceImpl&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;EmpMapper&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;implements&lt;/span&gt;&lt;span&gt; EmpService&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // ServiceImpl 已实现 IService 的所有方法&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; // ====== EmpController.java ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Tag&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;员工管理&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;RequestMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/emp&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; EmpController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Autowired&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     private&lt;/span&gt;&lt;span&gt; EmpService empService;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;分页查询&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/page&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Page&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;RequestParam&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;defaultValue&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;1&quot;&lt;/span&gt;&lt;span&gt;) Integer &lt;/span&gt;&lt;span&gt;current&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;RequestParam&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;defaultValue&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;10&quot;&lt;/span&gt;&lt;span&gt;) Integer &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; Page&amp;lt;&amp;gt;(current, size));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;新增员工&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PostMapping&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; save&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;RequestBody&lt;/span&gt;&lt;span&gt; Emp &lt;/span&gt;&lt;span&gt;emp&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;save&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;根据ID查询&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/{id}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Emp &lt;/span&gt;&lt;span&gt;getById&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;PathVariable&lt;/span&gt;&lt;span&gt; Integer &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;getById&lt;/span&gt;&lt;span&gt;(id);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;更新员工&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PutMapping&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; update&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;RequestBody&lt;/span&gt;&lt;span&gt; Emp &lt;/span&gt;&lt;span&gt;emp&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;updateById&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;删除员工&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;DeleteMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/{id}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; delete&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;PathVariable&lt;/span&gt;&lt;span&gt; Integer &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;removeById&lt;/span&gt;&lt;span&gt;(id);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;多模块项目中的逆向工程&lt;a href=&quot;#多模块项目中的逆向工程&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;多模块项目结构&lt;a href=&quot;#多模块项目结构&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;my-project/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── pom.xml                          ← 父 POM&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── my-project-common/               ← 通用模块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── pom.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── my-project-entity/               ← 实体模块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   ├── pom.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   └── src/main/java/com/example/entity/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; ├── my-project-mapper/               ← Mapper 模块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; │   ├── pom.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── src/main/java/com/example/mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── my-project-service/              ← Service 模块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── pom.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── src/main/java/com/example/service/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── my-project-web/                  ← Web 模块（启动模块）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── pom.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── src/main/resources/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│       ├── generatorConfig.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│       └── application.yml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└── my-project-generator/            ← 代码生成器模块（独立）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ├── pom.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    └── src/main/java/com/example/Generator.java&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;多模块 MBG 配置&lt;a href=&quot;#多模块-mbg-配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- generatorConfig.xml 放在 my-project-generator 模块中 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;generatorConfiguration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;multiModule&quot;&lt;/span&gt;&lt;span&gt; targetRuntime&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MyBatis3&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.SerializablePlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.ToStringPlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;suppressAllComments&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;jdbcConnection&lt;/span&gt;&lt;span&gt; driverClass&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.driver}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        connectionURL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.url}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        userId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.username}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        password&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.password}&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;useInformationSchema&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;jdbcConnection&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;javaTypeResolver&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;useJSR310Types&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;javaTypeResolver&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 实体类输出到 entity 模块 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;javaModelGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;../my-project-entity/src/main/java&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;trimStrings&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;javaModelGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- XML 输出到 web 模块的 resources --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;sqlMapGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;../my-project-web/src/main/resources&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;sqlMapGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- Mapper 接口输出到 mapper 模块 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;javaClientGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;XMLMAPPER&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;../my-project-mapper/src/main/java&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;javaClientGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;generatedKey&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt; sqlStatement&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MySql&quot;&lt;/span&gt;&lt;span&gt; identity&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;generatorConfiguration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;关键：&lt;/strong&gt; targetProject 使用相对路径 ../模块名/src/main/java 指向其他模块的源码目录。&lt;/p&gt;
&lt;h3&gt;多模块 MP Generator 配置&lt;a href=&quot;#多模块-mp-generator-配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; FastAutoGenerator.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(url, username, password)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     .&lt;/span&gt;&lt;span&gt;globalConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; builder&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         .&lt;/span&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;example&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         .&lt;/span&gt;&lt;span&gt;outputDir&lt;/span&gt;&lt;span&gt;(System.&lt;/span&gt;&lt;span&gt;getProperty&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;user.dir&quot;&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;/my-project-generator/src/main/java&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     .&lt;/span&gt;&lt;span&gt;packageConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; builder&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         .&lt;/span&gt;&lt;span&gt;parent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         // 实体类输出到 entity 模块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         .&lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;entity&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // Mapper 输出到 mapper 模块&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;mapper&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;pathInfo&lt;/span&gt;&lt;span&gt;(java.util.Map.&lt;/span&gt;&lt;span&gt;of&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            OutputFile.entity, &lt;/span&gt;&lt;span&gt;&quot;../my-project-entity/src/main/java&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            OutputFile.mapper, &lt;/span&gt;&lt;span&gt;&quot;../my-project-mapper/src/main/java&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            OutputFile.service, &lt;/span&gt;&lt;span&gt;&quot;../my-project-service/src/main/java&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            OutputFile.serviceImpl, &lt;/span&gt;&lt;span&gt;&quot;../my-project-service/src/main/java&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            OutputFile.controller, &lt;/span&gt;&lt;span&gt;&quot;../my-project-web/src/main/java&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            OutputFile.xml, &lt;/span&gt;&lt;span&gt;&quot;../my-project-web/src/main/resources/mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        ))&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;strategyConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; builder&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;addInclude&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;dept&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;entityBuilder&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;enableLombok&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;execute&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;实战案例一：MBG 完整项目&lt;a href=&quot;#实战案例一mbg-完整项目&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;项目搭建&lt;a href=&quot;#项目搭建&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;# 1. 创建 Maven 项目&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mvn&lt;/span&gt;&lt;span&gt; archetype:generate&lt;/span&gt;&lt;span&gt; -DgroupId=com.example&lt;/span&gt;&lt;span&gt; -DartifactId=mbg-demo&lt;/span&gt;&lt;span&gt; -DarchetypeArtifactId=maven-archetype-quickstart&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 2. 进入项目目录&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;cd&lt;/span&gt;&lt;span&gt; mbg-demo&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 3. 添加依赖（参考 III 章节 pom.xml）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;完整配置文件&lt;a href=&quot;#完整配置文件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;generatorConfig.xml:&lt;/strong&gt;&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;?&lt;/span&gt;&lt;span&gt;xml&lt;/span&gt;&lt;span&gt; version&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;1.0&quot;&lt;/span&gt;&lt;span&gt; encoding&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!&lt;/span&gt;&lt;span&gt;DOCTYPE&lt;/span&gt;&lt;span&gt; generatorConfiguration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         PUBLIC &quot;-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &quot;http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd&quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;generatorConfiguration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;properties&lt;/span&gt;&lt;span&gt; resource&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;generator.properties&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mysqlContext&quot;&lt;/span&gt;&lt;span&gt; targetRuntime&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MyBatis3&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             defaultModelType&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;conditional&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 插件 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.SerializablePlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.ToStringPlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.EqualsAndHashCodePlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 重命名 Example 为 Query --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.RenameExampleClassPlugin&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;searchString&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Example$&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;replaceString&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Query&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 注释生成器 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;suppressAllComments&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;suppressDate&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;addRemarkComments&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 数据库连接 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;jdbcConnection&lt;/span&gt;&lt;span&gt; driverClass&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.driver}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        connectionURL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.url}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        userId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.username}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        password&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;${jdbc.password}&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;useInformationSchema&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;jdbcConnection&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 类型解析 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;javaTypeResolver&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;forceBigDecimals&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;false&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;useJSR310Types&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;javaTypeResolver&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 实体类 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;javaModelGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/java&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;trimStrings&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;javaModelGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- XML --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;sqlMapGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/resources&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;sqlMapGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- Mapper --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;javaClientGenerator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;XMLMAPPER&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/java&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;javaClientGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;!-- 表配置 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableCountByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableDeleteByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableSelectByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;               enableUpdateByExample&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;generatedKey&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt; sqlStatement&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MySql&quot;&lt;/span&gt;&lt;span&gt; identity&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept&quot;&lt;/span&gt;&lt;span&gt; domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Dept&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            &amp;lt;&lt;/span&gt;&lt;span&gt;generatedKey&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept_id&quot;&lt;/span&gt;&lt;span&gt; sqlStatement&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MySql&quot;&lt;/span&gt;&lt;span&gt; identity&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;generatorConfiguration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;执行生成&lt;a href=&quot;#执行生成&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;# 方式一：Maven 命令&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mvn&lt;/span&gt;&lt;span&gt; mybatis-generator:generate&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 方式二：运行 Java 类&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 直接运行 Generator.java 的 main 方法&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;编写测试&lt;a href=&quot;#编写测试&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.test;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.example.entity.Emp;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.example.entity.EmpQuery;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.example.mapper.EmpMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.io.Resources;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.session.SqlSession;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.session.SqlSessionFactory;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.session.SqlSessionFactoryBuilder;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.junit.After;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.junit.Before;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; org.junit.Test;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.io.InputStream;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.math.BigDecimal;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; EmpMapperTest&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; SqlSession session;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; EmpMapper empMapper;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Before&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; setUp&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;throws&lt;/span&gt;&lt;span&gt; Exception {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        InputStream is &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; Resources.&lt;/span&gt;&lt;span&gt;getResourceAsStream&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;mybatis-config.xml&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        SqlSessionFactory factory &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; SqlSessionFactoryBuilder&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;build&lt;/span&gt;&lt;span&gt;(is);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        session &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; factory.&lt;/span&gt;&lt;span&gt;openSession&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        empMapper &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; session.&lt;/span&gt;&lt;span&gt;getMapper&lt;/span&gt;&lt;span&gt;(EmpMapper.class);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;After&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; tearDown&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (session &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            session.&lt;/span&gt;&lt;span&gt;close&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    // 测试1：插入&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; testInsert&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Emp emp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        emp.&lt;/span&gt;&lt;span&gt;setEmpName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;赵六&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        emp.&lt;/span&gt;&lt;span&gt;setGender&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;M&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        emp.&lt;/span&gt;&lt;span&gt;setEmail&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;zhaoliu@qq.com&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        emp.&lt;/span&gt;&lt;span&gt;setSalary&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; BigDecimal&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;13000&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        emp.&lt;/span&gt;&lt;span&gt;setDeptId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        int&lt;/span&gt;&lt;span&gt; rows &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper.&lt;/span&gt;&lt;span&gt;insert&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;插入行数: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; rows);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;主键回填: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; emp.&lt;/span&gt;&lt;span&gt;getEmpId&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         session.&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     // 测试2：按主键查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; testSelectByPrimaryKey&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         Emp emp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper.&lt;/span&gt;&lt;span&gt;selectByPrimaryKey&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     // 测试3：条件查询&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; testSelectByExample&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         EmpQuery query &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; EmpQuery&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         query.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;andGenderEqualTo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;M&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                 .&lt;/span&gt;&lt;span&gt;andSalaryGreaterThan&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; BigDecimal&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;10000&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         query.&lt;/span&gt;&lt;span&gt;setOrderByClause&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;salary DESC&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; list &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper.&lt;/span&gt;&lt;span&gt;selectByExample&lt;/span&gt;&lt;span&gt;(query);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         list.&lt;/span&gt;&lt;span&gt;forEach&lt;/span&gt;&lt;span&gt;(System.out&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;println);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     // 测试4：选择性更新&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; testUpdateByPrimaryKeySelective&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         Emp emp &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         emp.&lt;/span&gt;&lt;span&gt;setEmpId&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         emp.&lt;/span&gt;&lt;span&gt;setSalary&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; BigDecimal&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;20000&quot;&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         int&lt;/span&gt;&lt;span&gt; rows &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper.&lt;/span&gt;&lt;span&gt;updateByPrimaryKeySelective&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;更新行数: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; rows);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         session.&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     // 测试5：条件删除&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; testDeleteByExample&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         EmpQuery query &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; EmpQuery&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         query.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;andDeptIdIsNull&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         int&lt;/span&gt;&lt;span&gt; rows &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper.&lt;/span&gt;&lt;span&gt;deleteByExample&lt;/span&gt;&lt;span&gt;(query);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;删除行数: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; rows);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         session.&lt;/span&gt;&lt;span&gt;commit&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     // 测试6：条件计数&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     @&lt;/span&gt;&lt;span&gt;Test&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; testCountByExample&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        EmpQuery query &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; EmpQuery&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        query.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;andGenderEqualTo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;M&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        long&lt;/span&gt;&lt;span&gt; count &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; empMapper.&lt;/span&gt;&lt;span&gt;countByExample&lt;/span&gt;&lt;span&gt;(query);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;男性员工数量: &quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; count);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;实战案例二：MyBatis-Plus Generator 完整项目&lt;a href=&quot;#实战案例二mybatis-plus-generator-完整项目&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;项目搭建&lt;a href=&quot;#项目搭建-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- pom.xml 关键依赖 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springframework.boot&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;spring-boot-starter-web&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.baomidou&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-plus-spring-boot3-starter&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.5.7&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.baomidou&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-plus-generator&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;3.5.7&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.freemarker&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;freemarker&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;runtime&amp;lt;/&lt;/span&gt;&lt;span&gt;scope&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.projectlombok&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;lombok&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;gt;true&amp;lt;/&lt;/span&gt;&lt;span&gt;optional&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.springdoc&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;springdoc-openapi-starter-webmvc-ui&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;2.5.0&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;生成器代码&lt;a href=&quot;#生成器代码&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.generator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.annotation.IdType;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.generator.FastAutoGenerator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.generator.config.OutputFile;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.HashMap;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.Map;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; CodeGenerator&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; main&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;[] &lt;/span&gt;&lt;span&gt;args&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 数据库配置&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String url &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;jdbc:mysql://localhost:3306/mybatis_demo&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                     &quot;?&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     useSSL=false&amp;amp;serverTimezone=Asia/Shanghai&amp;amp;characterEncoding=utf8&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String username &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;root&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String password &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;123456&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 输出目录&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String projectPath &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; System.&lt;/span&gt;&lt;span&gt;getProperty&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;user.dir&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        FastAutoGenerator.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(url, username, password)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            .&lt;/span&gt;&lt;span&gt;globalConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; builder&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;author&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;example&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;outputDir&lt;/span&gt;&lt;span&gt;(projectPath &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;/src/main/java&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;enableSwagger&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;commentDate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;yyyy-MM-dd&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;disableOpenDir&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            .&lt;/span&gt;&lt;span&gt;packageConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                Map&amp;lt;&lt;/span&gt;&lt;span&gt;OutputFile&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; pathInfo &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; HashMap&amp;lt;&amp;gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                pathInfo.&lt;/span&gt;&lt;span&gt;put&lt;/span&gt;&lt;span&gt;(OutputFile.xml, projectPath &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &quot;/src/main/resources/mapper&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                builder&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;parent&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;com.example&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;entity&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;entity&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;mapper&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;mapper&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;service&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;serviceImpl&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;service.impl&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;controller&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;controller&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;pathInfo&lt;/span&gt;&lt;span&gt;(pathInfo);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            })&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            .&lt;/span&gt;&lt;span&gt;strategyConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; builder&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;addInclude&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;dept&quot;&lt;/span&gt;&lt;span&gt;)       &lt;/span&gt;&lt;span&gt;// 要生成的表&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;addTablePrefix&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;t_&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;sys_&quot;&lt;/span&gt;&lt;span&gt;)    &lt;/span&gt;&lt;span&gt;// 去掉表前缀&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;entityBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;naming&lt;/span&gt;&lt;span&gt;(NamingStrategy.underline_to_camel)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;columnNaming&lt;/span&gt;&lt;span&gt;(NamingStrategy.underline_to_camel)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;enableLombok&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;enableTableFieldAnnotation&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;idType&lt;/span&gt;&lt;span&gt;(IdType.AUTO)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;logicDeleteColumnName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;deleted&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;versionColumnName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;version&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;formatFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%s&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;mapperBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;enableMapperAnnotation&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;enableBaseResultMap&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;enableBaseColumnList&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;formatMapperFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sMapper&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;formatXmlFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sMapper&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;serviceBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;formatServiceFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sService&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;formatServiceImplFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sServiceImpl&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;controllerBuilder&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;enableRestStyle&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;enableHyphenStyle&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    .&lt;/span&gt;&lt;span&gt;formatFileName&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%sController&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            .&lt;/span&gt;&lt;span&gt;templateEngine&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; FreemarkerTemplateEngine&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            .&lt;/span&gt;&lt;span&gt;execute&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        System.out.&lt;/span&gt;&lt;span&gt;println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;✅ 代码生成完成！&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;自动填充处理器&lt;a href=&quot;#自动填充处理器&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.config;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.apache.ibatis.reflection.MetaObject;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.springframework.stereotype.Component;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.time.LocalDateTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * 自动填充处理器&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * 配合实体类 @TableField(fill = FieldFill.INSERT) 使用&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Component&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MyMetaObjectHandler&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; MetaObjectHandler&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; insertFill&lt;/span&gt;&lt;span&gt;(MetaObject &lt;/span&gt;&lt;span&gt;metaObject&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 新增时自动填充&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;strictInsertFill&lt;/span&gt;&lt;span&gt;(metaObject, &lt;/span&gt;&lt;span&gt;&quot;createTime&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            LocalDateTime.class, LocalDateTime.&lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;strictInsertFill&lt;/span&gt;&lt;span&gt;(metaObject, &lt;/span&gt;&lt;span&gt;&quot;updateTime&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            LocalDateTime.class, LocalDateTime.&lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; void&lt;/span&gt;&lt;span&gt; updateFill&lt;/span&gt;&lt;span&gt;(MetaObject &lt;/span&gt;&lt;span&gt;metaObject&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 更新时自动填充&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        this&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;strictUpdateFill&lt;/span&gt;&lt;span&gt;(metaObject, &lt;/span&gt;&lt;span&gt;&quot;updateTime&quot;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            LocalDateTime.class, LocalDateTime.&lt;/span&gt;&lt;span&gt;now&lt;/span&gt;&lt;span&gt;());&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;分页配置&lt;a href=&quot;#分页配置&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.config;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.annotation.DbType;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.springframework.context.annotation.Bean;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.springframework.context.annotation.Configuration;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; @&lt;/span&gt;&lt;span&gt;Configuration&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; MyBatisPlusConfig&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; MybatisPlusInterceptor &lt;/span&gt;&lt;span&gt;mybatisPlusInterceptor&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        MybatisPlusInterceptor interceptor &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; MybatisPlusInterceptor&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 分页插件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        interceptor.&lt;/span&gt;&lt;span&gt;addInnerInterceptor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            new&lt;/span&gt;&lt;span&gt; PaginationInnerInterceptor&lt;/span&gt;&lt;span&gt;(DbType.MYSQL));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; interceptor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;测试使用&lt;a href=&quot;#测试使用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.controller;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.baomidou.mybatisplus.extension.plugins.pagination.Page;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.example.entity.Emp;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; com.example.service.EmpService;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.annotations.Operation;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.annotations.tags.Tag;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.springframework.beans.factory.annotation.Autowired;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.springframework.web.bind.annotation.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Tag&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;员工管理&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RestController&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;RequestMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/emp&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; EmpController&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Autowired&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; EmpService empService;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;分页查询&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/page&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Page&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;RequestParam&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;defaultValue&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;1&quot;&lt;/span&gt;&lt;span&gt;) Integer &lt;/span&gt;&lt;span&gt;current&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;RequestParam&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;defaultValue&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;10&quot;&lt;/span&gt;&lt;span&gt;) Integer &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;new&lt;/span&gt;&lt;span&gt; Page&amp;lt;&amp;gt;(current, size));&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;条件分页查询&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/search&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Page&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;search&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;RequestParam&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;defaultValue&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;1&quot;&lt;/span&gt;&lt;span&gt;) Integer &lt;/span&gt;&lt;span&gt;current&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;RequestParam&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;defaultValue&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;10&quot;&lt;/span&gt;&lt;span&gt;) Integer &lt;/span&gt;&lt;span&gt;size&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;RequestParam&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;required&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;) String &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;RequestParam&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;required&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;) String &lt;/span&gt;&lt;span&gt;gender&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            @&lt;/span&gt;&lt;span&gt;RequestParam&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;required&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; false&lt;/span&gt;&lt;span&gt;) Integer &lt;/span&gt;&lt;span&gt;deptId&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        Page&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; page &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; Page&amp;lt;&amp;gt;(current, size);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;lambdaQuery&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;like&lt;/span&gt;&lt;span&gt;(name &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; !&lt;/span&gt;&lt;span&gt;name.&lt;/span&gt;&lt;span&gt;isEmpty&lt;/span&gt;&lt;span&gt;(), Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getEmpName, name)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;eq&lt;/span&gt;&lt;span&gt;(gender &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; !&lt;/span&gt;&lt;span&gt;gender.&lt;/span&gt;&lt;span&gt;isEmpty&lt;/span&gt;&lt;span&gt;(), Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getGender, gender)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;eq&lt;/span&gt;&lt;span&gt;(deptId &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt;, Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getDeptId, deptId)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;orderByDesc&lt;/span&gt;&lt;span&gt;(Emp&lt;/span&gt;&lt;span&gt;::&lt;/span&gt;&lt;span&gt;getSalary)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span&gt;(page);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;新增&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PostMapping&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; save&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;RequestBody&lt;/span&gt;&lt;span&gt; Emp &lt;/span&gt;&lt;span&gt;emp&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;save&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;批量新增&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PostMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/batch&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; saveBatch&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;RequestBody&lt;/span&gt;&lt;span&gt; List&amp;lt;&lt;/span&gt;&lt;span&gt;Emp&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;list&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;saveBatch&lt;/span&gt;&lt;span&gt;(list);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;根据ID查询&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;GetMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/{id}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; Emp &lt;/span&gt;&lt;span&gt;getById&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;PathVariable&lt;/span&gt;&lt;span&gt; Integer &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;getById&lt;/span&gt;&lt;span&gt;(id);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;更新&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;PutMapping&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; update&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;RequestBody&lt;/span&gt;&lt;span&gt; Emp &lt;/span&gt;&lt;span&gt;emp&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;updateById&lt;/span&gt;&lt;span&gt;(emp);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Operation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;summary&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;根据ID删除&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;DeleteMapping&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;/{id}&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; delete&lt;/span&gt;&lt;span&gt;(@&lt;/span&gt;&lt;span&gt;PathVariable&lt;/span&gt;&lt;span&gt; Integer &lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; empService.&lt;/span&gt;&lt;span&gt;removeById&lt;/span&gt;&lt;span&gt;(id);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;实战案例三：自定义插件生成 Swagger 注解&lt;a href=&quot;#实战案例三自定义插件生成-swagger-注解&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;需求&lt;a href=&quot;#需求&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;让 MBG 生成的实体类自动添加 Swagger/OpenAPI 注解：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;员工表&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;员工ID&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;员工姓名&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;自定义 Swagger 插件&lt;a href=&quot;#自定义-swagger-插件&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.generator;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.IntrospectedColumn;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.IntrospectedTable;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.PluginAdapter;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; org.mybatis.generator.api.dom.java.&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.util.List;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;/**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * 自定义 Swagger 注解插件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; * 自动给实体类和字段添加 @Schema 注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; SwaggerAnnotationPlugin&lt;/span&gt;&lt;span&gt; extends&lt;/span&gt;&lt;span&gt; PluginAdapter&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; String SCHEMA &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &quot;io.swagger.v3.oas.annotations.media.Schema&quot;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; validate&lt;/span&gt;&lt;span&gt;(List&amp;lt;&lt;/span&gt;&lt;span&gt;String&lt;/span&gt;&lt;span&gt;&amp;gt; &lt;/span&gt;&lt;span&gt;warnings&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 给实体类添加 @Schema 注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; modelBaseRecordClassGenerated&lt;/span&gt;&lt;span&gt;(TopLevelClass &lt;/span&gt;&lt;span&gt;topLevelClass&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                                  IntrospectedTable &lt;/span&gt;&lt;span&gt;introspectedTable&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 导入 @Schema&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        topLevelClass.&lt;/span&gt;&lt;span&gt;addImportedType&lt;/span&gt;&lt;span&gt;(SCHEMA);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 生成注解：@Schema(description = &quot;表注释&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String remark &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; introspectedTable.&lt;/span&gt;&lt;span&gt;getRemarks&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String description &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (remark &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; !&lt;/span&gt;&lt;span&gt;remark.&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;isEmpty&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                ?&lt;/span&gt;&lt;span&gt; remark&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                :&lt;/span&gt;&lt;span&gt; introspectedTable.&lt;/span&gt;&lt;span&gt;getFullyQualifiedTable&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;toString&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        topLevelClass.&lt;/span&gt;&lt;span&gt;addAnnotation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;@Schema(description = &lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; escape&lt;/span&gt;&lt;span&gt;(description) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &quot;&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;)&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 给字段添加 @Schema 注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Override&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    public&lt;/span&gt;&lt;span&gt; boolean&lt;/span&gt;&lt;span&gt; modelFieldGenerated&lt;/span&gt;&lt;span&gt;(Field &lt;/span&gt;&lt;span&gt;field&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                        TopLevelClass &lt;/span&gt;&lt;span&gt;topLevelClass&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                        IntrospectedColumn &lt;/span&gt;&lt;span&gt;introspectedColumn&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                        IntrospectedTable &lt;/span&gt;&lt;span&gt;introspectedTable&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                                        ModelClassType &lt;/span&gt;&lt;span&gt;modelClassType&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 确保 @Schema 已导入&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        if&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;span&gt;topLevelClass.&lt;/span&gt;&lt;span&gt;getImportedTypes&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;stream&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                .&lt;/span&gt;&lt;span&gt;anyMatch&lt;/span&gt;&lt;span&gt;(t &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; t.&lt;/span&gt;&lt;span&gt;getFullyQualifiedName&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;equals&lt;/span&gt;&lt;span&gt;(SCHEMA))) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;            topLevelClass.&lt;/span&gt;&lt;span&gt;addImportedType&lt;/span&gt;&lt;span&gt;(SCHEMA);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        // 生成字段注解&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String remark &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; introspectedColumn.&lt;/span&gt;&lt;span&gt;getRemarks&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        String description &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; (remark &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; null&lt;/span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;/span&gt;&lt;span&gt; !&lt;/span&gt;&lt;span&gt;remark.&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;isEmpty&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                ?&lt;/span&gt;&lt;span&gt; remark&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                :&lt;/span&gt;&lt;span&gt; introspectedColumn.&lt;/span&gt;&lt;span&gt;getActualColumnName&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        field.&lt;/span&gt;&lt;span&gt;addAnnotation&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;@Schema(description = &lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt; +&lt;/span&gt;&lt;span&gt; escape&lt;/span&gt;&lt;span&gt;(description) &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;)&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; true&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    /**&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     * 转义特殊字符&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     */&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String &lt;/span&gt;&lt;span&gt;escape&lt;/span&gt;&lt;span&gt;(String &lt;/span&gt;&lt;span&gt;s&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        return&lt;/span&gt;&lt;span&gt; s.&lt;/span&gt;&lt;span&gt;replace&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\&quot;&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\\\&quot;&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;replace&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot; &quot;&lt;/span&gt;&lt;span&gt;).&lt;/span&gt;&lt;span&gt;trim&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;配置使用&lt;a href=&quot;#配置使用&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mysqlContext&quot;&lt;/span&gt;&lt;span&gt; targetRuntime&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MyBatis3&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- ★ Swagger 注解插件 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.generator.SwaggerAnnotationPlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- ★ Lombok 插件（配合使用） --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.generator.LombokPlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;!-- Serializable --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;org.mybatis.generator.plugins.SerializablePlugin&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;suppressAllComments&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;commentGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;jdbcConnection&lt;/span&gt;&lt;span&gt; driverClass&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.mysql.cj.jdbc.Driver&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    connectionURL&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;jdbc:mysql://localhost:3306/mybatis_demo&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                    userId&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;root&quot;&lt;/span&gt;&lt;span&gt; password&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;123456&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;useInformationSchema&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;jdbcConnection&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;javaTypeResolver&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;useJSR310Types&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;javaTypeResolver&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;javaModelGenerator&lt;/span&gt;&lt;span&gt; targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.entity&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                        targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/java&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;property&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;trimStrings&quot;&lt;/span&gt;&lt;span&gt; value&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;javaModelGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;sqlMapGenerator&lt;/span&gt;&lt;span&gt; targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                     targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/resources&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;sqlMapGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;javaClientGenerator&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;XMLMAPPER&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                         targetPackage&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.mapper&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;                         targetProject&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;src/main/java&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;javaClientGenerator&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;generatedKey&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt; sqlStatement&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MySql&quot;&lt;/span&gt;&lt;span&gt; identity&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;生成的实体类效果&lt;a href=&quot;#生成的实体类效果-1&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; package&lt;/span&gt;&lt;span&gt; com.example.entity;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; io.swagger.v3.oas.annotations.media.Schema;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.io.Serializable;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.math.BigDecimal;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.time.LocalDate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; java.time.LocalDateTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; lombok.AllArgsConstructor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; import&lt;/span&gt;&lt;span&gt; lombok.Builder;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; lombok.Data;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; lombok.NoArgsConstructor;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Data&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Builder&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;NoArgsConstructor&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;AllArgsConstructor&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;@&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;员工表&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;public&lt;/span&gt;&lt;span&gt; class&lt;/span&gt;&lt;span&gt; Emp&lt;/span&gt;&lt;span&gt; implements&lt;/span&gt;&lt;span&gt; Serializable&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; static&lt;/span&gt;&lt;span&gt; final&lt;/span&gt;&lt;span&gt; long&lt;/span&gt;&lt;span&gt; serialVersionUID &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; 1L&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;员工ID&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer empId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;员工姓名&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String empName;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;性别 M-男 F-女&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String gender;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;邮箱&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; String email;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;工资&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; BigDecimal salary;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;所属部门ID&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; Integer deptId;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;入职日期&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDate hireDate;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;创建时间&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDateTime createTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    @&lt;/span&gt;&lt;span&gt;Schema&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;description&lt;/span&gt;&lt;span&gt; =&lt;/span&gt;&lt;span&gt; &quot;更新时间&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    private&lt;/span&gt;&lt;span&gt; LocalDateTime updateTime;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;常见问题与排错&lt;a href=&quot;#常见问题与排错&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;生成后没有表注释和字段注释&lt;a href=&quot;#生成后没有表注释和字段注释&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原因：&lt;/strong&gt; MySQL 8.x 默认不返回注释信息。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决：&lt;/strong&gt; 在 &amp;lt;jdbcConnection&amp;gt; 中添加 &amp;lt;property name=“useInformationSchema” value=“true”/&amp;gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;jdbcConnection ...&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;useInformationSchema&quot; value=&quot;true&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/jdbcConnection&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;日期类型生成的是 Date 而不是 LocalDateTime&lt;a href=&quot;#日期类型生成的是-date-而不是-localdatetime&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原因：&lt;/strong&gt; 默认使用 java.util.Date。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决：&lt;/strong&gt; 在 &amp;lt;javaTypeResolver&amp;gt; 中开启 JSR-310：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;javaTypeResolver&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;useJSR310Types&quot; value=&quot;true&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/javaTypeResolver&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意：此属性在 MBG 1.4.0+ 才支持。DATETIME → LocalDateTime，DATE → LocalDate，TIME → LocalTime。&lt;/p&gt;
&lt;h3&gt;文件覆盖问题：XML 文件没有完全覆盖&lt;a href=&quot;#文件覆盖问题xml-文件没有完全覆盖&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原因：&lt;/strong&gt; MBG 默认对 XML 文件使用 &lt;strong&gt;merge（合并）&lt;/strong&gt; 策略，而不是完全覆盖。这是为了保护你手写的自定义 SQL。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决：&lt;/strong&gt; 使用 UnmergeableXmlMapperPlugin 插件强制覆盖：&lt;/p&gt;
&lt;p&gt;1&amp;lt;plugin type=“org.mybatis.generator.plugins.UnmergeableXmlMapperPlugin”/&amp;gt;&lt;/p&gt;
&lt;h3&gt;生成的包名多了一层 schema 名&lt;a href=&quot;#生成的包名多了一层-schema-名&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原因：&lt;/strong&gt; enableSubPackages 设为 true 时，会将 schema 名作为包的后缀。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决：&lt;/strong&gt; 设置 enableSubPackages=“false”：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;javaModelGenerator targetPackage=&quot;com.example.entity&quot; ...&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;property name=&quot;enableSubPackages&quot; value=&quot;false&quot;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/javaModelGenerator&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;主键没有回填（insert 后实体类中 id 为 null）&lt;a href=&quot;#主键没有回填insert-后实体类中-id-为-null&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原因：&lt;/strong&gt; 没有配置 &amp;lt;generatedKey&amp;gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决：&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt; tableName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp&quot;&lt;/span&gt;&lt;span&gt; domainObjectName&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;Emp&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;generatedKey&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt; sqlStatement&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MySql&quot;&lt;/span&gt;&lt;span&gt; identity&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Maven 插件运行时找不到驱动&lt;a href=&quot;#maven-插件运行时找不到驱动&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原因：&lt;/strong&gt; Maven 插件的 classpath 中没有 MySQL 驱动。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决：&lt;/strong&gt; 在 &amp;lt;plugin&amp;gt; 的 &amp;lt;dependencies&amp;gt; 中添加驱动：&lt;/p&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis.generator&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-generator-maven-plugin&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;1.4.2&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     &amp;lt;&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         &amp;lt;&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;com.mysql&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mysql-connector-j&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;             &amp;lt;&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;8.0.33&amp;lt;/&lt;/span&gt;&lt;span&gt;version&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span&gt;dependency&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;dependencies&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;MySQL 关键字冲突（如&lt;code&gt;desc&lt;/code&gt;, &lt;code&gt;order&lt;/code&gt;, &lt;code&gt;key&lt;/code&gt;）&lt;a href=&quot;#mysql-关键字冲突如desc-order-key&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原因：&lt;/strong&gt; 表名或字段名是 MySQL 保留字。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决：&lt;/strong&gt; 在 context 上配置分隔符：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;mysqlContext&quot;&lt;/span&gt;&lt;span&gt; targetRuntime&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;MyBatis3&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         autoDelimitKeywords&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;true&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         beginningDelimiter&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;`&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         endingDelimiter&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;`&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;或者在 table 上配置：&lt;/p&gt;
&lt;p&gt;1&amp;lt;table tableName=“order” delimitIdentifiers=“true”&amp;gt;&lt;/p&gt;
&lt;h3&gt;MP Generator 生成的代码在错误的目录&lt;a href=&quot;#mp-generator-生成的代码在错误的目录&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原因：&lt;/strong&gt; outputDir 路径不正确。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决：&lt;/strong&gt; 使用 System.getProperty(“user.dir”) 确保路径正确：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;String projectPath &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; System.&lt;/span&gt;&lt;span&gt;getProperty&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;user.dir&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;FastAutoGenerator.&lt;/span&gt;&lt;span&gt;create&lt;/span&gt;&lt;span&gt;(url, username, password)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    .&lt;/span&gt;&lt;span&gt;globalConfig&lt;/span&gt;&lt;span&gt;(builder &lt;/span&gt;&lt;span&gt;-&amp;gt;&lt;/span&gt;&lt;span&gt; builder&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        .&lt;/span&gt;&lt;span&gt;outputDir&lt;/span&gt;&lt;span&gt;(projectPath &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &quot;/src/main/java&quot;&lt;/span&gt;&lt;span&gt;)  &lt;/span&gt;&lt;span&gt;// 绝对路径&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    )&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;MBG 生成文件中文乱码&lt;a href=&quot;#mbg-生成文件中文乱码&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;原因：&lt;/strong&gt; 编码不一致。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;解决：&lt;/strong&gt; 在 pom.xml 中配置编码：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;properties&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;project.build.sourceEncoding&amp;gt;UTF-8&amp;lt;/project.build.sourceEncoding&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/properties&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;并在 Maven 插件中配置：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;org.mybatis.generator&amp;lt;/&lt;/span&gt;&lt;span&gt;groupId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;mybatis-generator-maven-plugin&amp;lt;/&lt;/span&gt;&lt;span&gt;artifactId&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span&gt;configurationFile&lt;/span&gt;&lt;span&gt;&amp;gt;src/main/resources/generatorConfig.xml&amp;lt;/&lt;/span&gt;&lt;span&gt;configurationFile&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span&gt;configuration&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;plugin&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;MP Generator 3.5.x API 变化&lt;a href=&quot;#mp-generator-35x-api-变化&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;问题：&lt;/strong&gt; 从 3.4.x 升级到 3.5.x 后 API 不兼容。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要变化：&lt;/strong&gt;&lt;/p&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;3.4.x（旧）&lt;/th&gt;&lt;th&gt;3.5.x（新）&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;new AutoGenerator()&lt;/td&gt;&lt;td&gt;new AutoGenerator(dataSourceConfig)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;generator.setDataSource(config)&lt;/td&gt;&lt;td&gt;构造器参数传入&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;generator.setGlobalConfig(config)&lt;/td&gt;&lt;td&gt;generator.global(config)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;generator.setStrategy(config)&lt;/td&gt;&lt;td&gt;generator.strategy(config)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;generator.setPackageInfo(config)&lt;/td&gt;&lt;td&gt;generator.packageInfo(config)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;generator.setTemplate(config)&lt;/td&gt;&lt;td&gt;generator.template(config)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;最佳实践&lt;a href=&quot;#最佳实践&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;生成策略选择&lt;a href=&quot;#生成策略选择&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;是否需要 Service / Controller？&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 是 → 使用 MyBatis-Plus Generator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│        （自带 Service / Controller / BaseMapper）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└── 否 → 使用 MyBatis Generator&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;         （仅生成 Entity / Mapper / XML / Example）&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;将生成代码与自定义代码分离&lt;a href=&quot;#将生成代码与自定义代码分离&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;核心原则：生成的代码可以随时重新生成，不要直接修改。&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;正确的做法：&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 生成的 Mapper 接口 ← 保持不变（继承 BaseMapper 扩展）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 自定义 SQL ← 新建 CustomXxxMapper.java 或在同一 XML 中追加&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└── 业务逻辑 ← 写在 Service 层&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;错误的做法：&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 直接在生成的 EmpMapper.java 中添加方法 ← 重新生成会被覆盖&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── 直接在生成的 EmpMapper.xml 中修改 SQL ← merge 可能保留，但有风险&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;└── 直接在生成的 Emp.java 中添加逻辑 ← 重新生成会被覆盖&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;XML 自定义 SQL 扩展方案&lt;a href=&quot;#xml-自定义-sql-扩展方案&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; &amp;lt;!-- EmpMapper.xml — MBG 生成的部分保持不变 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- ====== 以下为手动追加的自定义 SQL ====== --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;!-- 多表关联查询 --&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;selectEmpWithDept&quot;&lt;/span&gt;&lt;span&gt; resultMap&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;EmpWithDeptResultMap&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     SELECT e.*, d.dept_name, d.location&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     FROM emp e&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;     LEFT JOIN dept d ON e.dept_id = d.dept_id&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    WHERE e.emp_id = #{empId}&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt; id&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;EmpWithDeptResultMap&quot;&lt;/span&gt;&lt;span&gt; type&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;com.example.dto.EmpDeptDTO&quot;&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_id&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empId&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;emp_name&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;empName&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;gender&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;gender&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;salary&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;dept_name&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;deptName&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;    &amp;lt;&lt;/span&gt;&lt;span&gt;result&lt;/span&gt;&lt;span&gt; column&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;location&quot;&lt;/span&gt;&lt;span&gt; property&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;&quot;location&quot;&lt;/span&gt;&lt;span&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;&amp;lt;/&lt;/span&gt;&lt;span&gt;resultMap&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;配置管理建议&lt;a href=&quot;#配置管理建议&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt;项目结构建议：&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;├── src/main/resources/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── generator/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   ├── generatorConfig.xml      ← MBG 配置&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   ├── generator.properties     ← 数据库连接属性&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   └── generator-dev.properties ← 开发环境属性（可选）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   ├── mapper/&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   │   └── EmpMapper.xml            ← 生成的 XML&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;│   └── mybatis-config.xml&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;生成 vs 手写决策表&lt;a href=&quot;#生成-vs-手写决策表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;场景&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;建议方式&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;单表 CRUD&lt;/td&gt;&lt;td&gt;逆向工程生成&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;单表条件查询&lt;/td&gt;&lt;td&gt;MBG 的 Example 或 MP 的 LambdaQueryWrapper&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;多表 JOIN 查询&lt;/td&gt;&lt;td&gt;手写 SQL（XML 或注解）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;复杂统计报表&lt;/td&gt;&lt;td&gt;手写 SQL&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;分页查询&lt;/td&gt;&lt;td&gt;MP 分页插件&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;批量操作&lt;/td&gt;&lt;td&gt;MP 的 saveBatch / updateBatchById&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;速查表&lt;a href=&quot;#速查表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;MBG 配置元素速查表&lt;a href=&quot;#mbg-配置元素速查表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;






































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;元素&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;作用&lt;/th&gt;&lt;th&gt;必填&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;generatorConfiguration&amp;gt;&lt;/td&gt;&lt;td&gt;根&lt;strong&gt;元素&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;properties&amp;gt;&lt;/td&gt;&lt;td&gt;引入属性文件&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;classPathEntry&amp;gt;&lt;/td&gt;&lt;td&gt;数据库驱动路径&lt;/td&gt;&lt;td&gt;Maven 方式可省&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;context&amp;gt;&lt;/td&gt;&lt;td&gt;生成上下文&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;plugin&amp;gt;&lt;/td&gt;&lt;td&gt;插件配置&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;commentGenerator&amp;gt;&lt;/td&gt;&lt;td&gt;注释生成器&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;jdbcConnection&amp;gt;&lt;/td&gt;&lt;td&gt;数据库连接&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;javaTypeResolver&amp;gt;&lt;/td&gt;&lt;td&gt;类型解析器&lt;/td&gt;&lt;td&gt;否&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;javaModelGenerator&amp;gt;&lt;/td&gt;&lt;td&gt;实体类生成器&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;sqlMapGenerator&amp;gt;&lt;/td&gt;&lt;td&gt;XML 生成器&lt;/td&gt;&lt;td&gt;XMLMAPPER 模式必填&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;javaClientGenerator&amp;gt;&lt;/td&gt;&lt;td&gt;Mapper 接口生成器&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&amp;lt;table&amp;gt;&lt;/td&gt;&lt;td&gt;表配置&lt;/td&gt;&lt;td&gt;是&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;MBG 内置插件速查表&lt;a href=&quot;#mbg-内置插件速查表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;

















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;插件&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;功能&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;SerializablePlugin&lt;/td&gt;&lt;td&gt;实体类实现 Serializable&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ToStringPlugin&lt;/td&gt;&lt;td&gt;生成 toString()&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;EqualsAndHashCodePlugin&lt;/td&gt;&lt;td&gt;生成 equals() 和 hashCode()&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;FluentBuilderMethodsPlugin&lt;/td&gt;&lt;td&gt;链式 setter&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;RowBoundsPlugin&lt;/td&gt;&lt;td&gt;RowBounds 分页&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;RenameExampleClassPlugin&lt;/td&gt;&lt;td&gt;重命名 Example 类&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MapperNamePlugin&lt;/td&gt;&lt;td&gt;自定义 Mapper 名称&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;UnmergeableXmlMapperPlugin&lt;/td&gt;&lt;td&gt;XML 强制覆盖&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CaseInsensitiveLikePlugin&lt;/td&gt;&lt;td&gt;大小写不敏感 LIKE&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VirtualKeyPlugin&lt;/td&gt;&lt;td&gt;虚拟主键&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;MBG targetRuntime 速查表&lt;a href=&quot;#mbg-targetruntime-速查表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;



































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;值&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;生成 &lt;strong&gt;Example&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;生成 &lt;strong&gt;XML&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;MyBatis3&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;完整版（默认）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MyBatis3Simple&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;简化版（仅基本 CRUD）&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MyBatis3DynamicSql&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;动态 SQL DSL 版&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MyBatis3Kotlin&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;Kotlin 版&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;MP Generator 配置速查表&lt;a href=&quot;#mp-generator-配置速查表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;




























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;配置项&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;方法&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;作者&lt;/td&gt;&lt;td&gt;globalConfig.author(“xxx”)&lt;/td&gt;&lt;td&gt;注释中的作者名&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;输出目录&lt;/td&gt;&lt;td&gt;globalConfig.outputDir(“path”)&lt;/td&gt;&lt;td&gt;代码输出根目录&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Swagger&lt;/td&gt;&lt;td&gt;globalConfig.enableSwagger()&lt;/td&gt;&lt;td&gt;开启 Swagger 注解&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;父包&lt;/td&gt;&lt;td&gt;packageConfig.parent(“com.xxx”)&lt;/td&gt;&lt;td&gt;根包名&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;表名&lt;/td&gt;&lt;td&gt;strategyConfig.addInclude(“table”)&lt;/td&gt;&lt;td&gt;指定要生成的表&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;表前缀&lt;/td&gt;&lt;td&gt;strategyConfig.addTablePrefix(“t_“)&lt;/td&gt;&lt;td&gt;去掉表前缀&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Lombok&lt;/td&gt;&lt;td&gt;entityBuilder.enableLombok()&lt;/td&gt;&lt;td&gt;使用 Lombok&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;主键策略&lt;/td&gt;&lt;td&gt;entityBuilder.idType(IdType.AUTO)&lt;/td&gt;&lt;td&gt;主键生成策略&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;命名策略&lt;/td&gt;&lt;td&gt;entityBuilder.naming(…)&lt;/td&gt;&lt;td&gt;下划线转驼峰&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;RestController&lt;/td&gt;&lt;td&gt;controllerBuilder.enableRestStyle()&lt;/td&gt;&lt;td&gt;REST 风格&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Example 方法速查表&lt;a href=&quot;#example-方法速查表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; EmpExample example &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; new&lt;/span&gt;&lt;span&gt; EmpExample&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; // 创建 AND 条件组&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; EmpExample.Criteria criteria &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; example.&lt;/span&gt;&lt;span&gt;createCriteria&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; // 等值&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; criteria.&lt;/span&gt;&lt;span&gt;andXxxEqualTo&lt;/span&gt;&lt;span&gt;(value);          &lt;/span&gt;&lt;span&gt;// = value&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; criteria.&lt;/span&gt;&lt;span&gt;andXxxNotEqualTo&lt;/span&gt;&lt;span&gt;(value);       &lt;/span&gt;&lt;span&gt;// &amp;lt;&amp;gt; value&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 范围&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;criteria.&lt;/span&gt;&lt;span&gt;andXxxGreaterThan&lt;/span&gt;&lt;span&gt;(value);      &lt;/span&gt;&lt;span&gt;// &amp;gt; value&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;criteria.&lt;/span&gt;&lt;span&gt;andXxxGreaterThanOrEqualTo&lt;/span&gt;&lt;span&gt;(value); &lt;/span&gt;&lt;span&gt;// &amp;gt;= value&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;criteria.&lt;/span&gt;&lt;span&gt;andXxxLessThan&lt;/span&gt;&lt;span&gt;(value);         &lt;/span&gt;&lt;span&gt;// &amp;lt; value&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;criteria.&lt;/span&gt;&lt;span&gt;andXxxLessThanOrEqualTo&lt;/span&gt;&lt;span&gt;(value); &lt;/span&gt;&lt;span&gt;// &amp;lt;= value&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;criteria.&lt;/span&gt;&lt;span&gt;andXxxBetween&lt;/span&gt;&lt;span&gt;(v1, v2);        &lt;/span&gt;&lt;span&gt;// BETWEEN v1 AND v2&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;criteria.&lt;/span&gt;&lt;span&gt;andXxxNotBetween&lt;/span&gt;&lt;span&gt;(v1, v2);     &lt;/span&gt;&lt;span&gt;// NOT BETWEEN&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 集合&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;criteria.&lt;/span&gt;&lt;span&gt;andXxxIn&lt;/span&gt;&lt;span&gt;(list);               &lt;/span&gt;&lt;span&gt;// IN (...)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;criteria.&lt;/span&gt;&lt;span&gt;andXxxNotIn&lt;/span&gt;&lt;span&gt;(list);            &lt;/span&gt;&lt;span&gt;// NOT IN (...)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 模糊&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;criteria.&lt;/span&gt;&lt;span&gt;andXxxLike&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%keyword%&quot;&lt;/span&gt;&lt;span&gt;);      &lt;/span&gt;&lt;span&gt;// LIKE &apos;%keyword%&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;criteria.&lt;/span&gt;&lt;span&gt;andXxxNotLike&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;%keyword%&quot;&lt;/span&gt;&lt;span&gt;);   &lt;/span&gt;&lt;span&gt;// NOT LIKE &apos;%keyword%&apos;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// NULL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;criteria.&lt;/span&gt;&lt;span&gt;andXxxIsNull&lt;/span&gt;&lt;span&gt;();               &lt;/span&gt;&lt;span&gt;// IS NULL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;criteria.&lt;/span&gt;&lt;span&gt;andXxxIsNotNull&lt;/span&gt;&lt;span&gt;();            &lt;/span&gt;&lt;span&gt;// IS NOT NULL&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// OR 条件组&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example.&lt;/span&gt;&lt;span&gt;or&lt;/span&gt;&lt;span&gt;().&lt;/span&gt;&lt;span&gt;andXxxEqualTo&lt;/span&gt;&lt;span&gt;(value);     &lt;/span&gt;&lt;span&gt;// OR (...)&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 排序&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example.&lt;/span&gt;&lt;span&gt;setOrderByClause&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;salary DESC&quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;// 去重&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;example.&lt;/span&gt;&lt;span&gt;setDistinct&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;类型映射速查表&lt;a href=&quot;#类型映射速查表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;































































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;MySQL 类型&lt;/th&gt;&lt;th&gt;Java 类型（&lt;code&gt;useJSR310Types=true&lt;/code&gt;）&lt;/th&gt;&lt;th&gt;JDBC 类型&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;INT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Integer&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;INTEGER&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;BIGINT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Long&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;BIGINT&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;TINYINT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Integer&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;TINYINT&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;SMALLINT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Integer&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;SMALLINT&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DECIMAL&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;BigDecimal&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;DECIMAL&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;VARCHAR&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;String&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;VARCHAR&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;CHAR&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;String&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;CHAR&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;TEXT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;String&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;LONGVARCHAR&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DATE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;LocalDate&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;DATE&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DATETIME&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;LocalDateTime&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;TIME&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;LocalTime&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;TIME&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;LocalDateTime&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;TIMESTAMP&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;BLOB&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;byte[]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;LONGVARBINARY&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;BIT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Boolean&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;BIT&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;FLOAT&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Float&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;FLOAT&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;DOUBLE&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;Double&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;DOUBLE&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;JSON&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;String&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;VARCHAR&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;常用命令速查表&lt;a href=&quot;#常用命令速查表&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;pre&gt;&lt;code&gt;&lt;span&gt;&lt;span&gt; # ====== MBG ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; # Maven 插件执行&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; mvn&lt;/span&gt;&lt;span&gt; mybatis-generator:generate&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; # 指定配置文件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; mvn&lt;/span&gt;&lt;span&gt; mybatis-generator:generate&lt;/span&gt;&lt;span&gt; -DconfigurationFile=src/main/resources/generatorConfig.xml&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt; # 不覆盖已有文件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mvn&lt;/span&gt;&lt;span&gt; mybatis-generator:generate&lt;/span&gt;&lt;span&gt; -Doverwrite=false&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 命令行执行&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;java&lt;/span&gt;&lt;span&gt; -jar&lt;/span&gt;&lt;span&gt; mybatis-generator-core-1.4.2.jar&lt;/span&gt;&lt;span&gt; -configfile&lt;/span&gt;&lt;span&gt; generatorConfig.xml&lt;/span&gt;&lt;span&gt; -overwrite&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# ====== MP Generator ======&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 直接运行 main 方法（IDE 中右键运行）&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;# 或使用 Maven exec 插件&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;&lt;span&gt;mvn&lt;/span&gt;&lt;span&gt; exec:java&lt;/span&gt;&lt;span&gt; -Dexec.mainClass=&lt;/span&gt;&lt;span&gt;&quot;com.example.generator.CodeGenerator&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;总结：&lt;/strong&gt; MyBatis 逆向工程的核心在于理解「数据库表结构 → Java 代码」的自动映射过程。MyBatis Generator 是官方工具，稳定可靠，适合生成基础 DAO 层代码；MyBatis-Plus Generator 功能更丰富，能一键生成从 Entity 到 Controller 的全栈代码。两者都可以通过自定义插件和模板深度定制生成结果。掌握逆向工程可以大幅提升开发效率，但需谨记：&lt;strong&gt;应将可重复生成的代码与自定义代码分离，并在重新生成前确认覆盖范围；扩展查询可放在独立 Mapper、扩展接口或自定义 SQL 中&lt;/strong&gt;。&lt;/p&gt;</content:encoded><category>category:课程培训</category><category>category:华育兴业</category><category>category:框架</category><category>tag:MyBatis</category></item></channel></rss>