常平营销网站建设什么网站能看男女做暧

张小明 2026/3/2 16:31:50
常平营销网站建设,什么网站能看男女做暧,网站后台信息发布这样做,phpcms 手机网站模板目录 MyBatis-Plus 新手完全攻略#xff1a;从入门到精通 1. 什么是 MyBatis-Plus#xff1f;(核心概念) 1.1 背景知识#xff1a;从 JDBC 到 ORM 的进化之路 1.2 MP 的出现#xff1a;懒人的福音与效率的飞跃 2. 代码中的核心知识点详解与避坑指南 2.1 实体类 (Enti…目录MyBatis-Plus 新手完全攻略从入门到精通1. 什么是 MyBatis-Plus(核心概念)1.1 背景知识从 JDBC 到 ORM 的进化之路1.2 MP 的出现懒人的福音与效率的飞跃2. 代码中的核心知识点详解与避坑指南2.1 实体类 (Entity) 与 Lombok 的最佳实践2.2 注解映射 (Mapping Annotations) —— MP 是如何“看懂”数据库的2.3 BaseMapper 的泛型魔法3. 条件构造器 (Wrapper) - 代码中的重难点3.1 QueryWrapper (基础版 —— 并不推荐在生产环境大量使用)3.2 LambdaQueryWrapper (进阶推荐版 —— 必须掌握)4. 扩展知识点 (面试与实战必知)4.1 逻辑删除 (Logical Delete) —— 数据安全的安全带4.2 自动填充 (Auto Fill) —— 告别重复劳动4.3 为什么不要在循环中调用数据库(N1 问题)5. 如何阅读接下来的代码MyBatis-Plus 实战项目运行指南第一步环境准备 (必看)第二步搭建工程骨架第三步复制文件 (核心步骤)第四步初始化数据库第五步运行测试1. 批量修改数据 (UpdateWrapper)2. 数学运算更新 (SQL 片段)3. 单条更新 (UpdateById)4. 精准查询 (LambdaQueryWrapper)5. 批量查询 (SelectByIds)6. 条件更新 (QueryWrapper)7. 删除操作 (Delete)8. 插入新用户 (Insert) 总结方法一使用 IDEA 的“断点调试” (Debug 模式) —— 上帝视角 ️‍♂️方法二手动“单步执行” —— 稳扎稳打 方法三在代码里“强行睡觉” (不推荐但直观) 总结建议你好作为新手小白面对 MyBatis-Plus (MP) 这样强大的框架感到困惑是很正常的。MyBatis-Plus 其实就像是给 MyBatis 穿上了一套“钢铁侠战衣”让原本繁琐的数据库操作变得极其简单。为了让你能够彻底理解我为你准备了一份超详细的沉浸式学习指南。这不仅仅是代码更是一份涵盖了原理、扩展知识和最佳实践的教程。我为你生成了 5 个文件MyBatisPlus_Guide.md:核心教程文档。包含对所有知识点的深度解析、扩展说明、背景知识如 ORM、Lambda 表达式原理以及“为什么这样写”的解释。请务必配合代码阅读。UserInfo.java:实体类代码。包含极其详细的注解和字段说明。UserInfoMapper.java:Mapper 接口代码。包含自定义 SQL 的定义。MybatisPlusTests.java:测试用例代码。这是核心包含了 PDF 中所有的增删改查、复杂查询、Lambda 构造器等操作每一行都有详细注释。schema.sql:数据库脚本。用于初始化环境。请先阅读Guide 文档然后对照Tests 代码进行实践。MyBatis-Plus 超详细学习指南 (新手必读).mdMyBatis-Plus 新手完全攻略从入门到精通1. 什么是 MyBatis-Plus(核心概念)1.1 背景知识从 JDBC 到 ORM 的进化之路在学习 MyBatis-Plus (简称 MP) 之前你需要先理解为什么我们需要它。这一切都要从 Java 连接数据库的历史说起JDBC (Java Database Connectivity) —— 痛苦的起点:这是 Java 连接数据库的最底层标准。虽然功能强大但写起来非常折磨人。繁琐的样板代码为了执行一个简单的 SQL你需要手动加载驱动、通过DriverManager获取连接、创建Statement、处理ResultSet结果集最后还要在finally块中小心翼翼地关闭资源以防内存泄漏。硬编码的噩梦SQL 语句是写死在 Java 代码里的字符串。一旦数据库字段改名你需要在 Java 代码里满世界搜索替换极易出错。ORM (Object-Relational Mapping) —— 桥梁:为了解决上述痛苦ORM对象关系映射应运而生。它的核心思想是建立表 (Table) 和 类 (Class) 之间的映射关系让程序员像操作 Java 对象一样操作数据库。数据库表的一行数据 (Row) --- Java 类的一个对象 (Object)数据库表的列 (Column) --- Java 类的属性 (Field)MyBatis是一个优秀的“半自动化” ORM 框架。它成功地把 SQL 从 Java 代码中剥离到了 XML 配置文件中解决了硬编码问题。但它仍然要求你为每一个查询方法甚至是最简单的selectById编写 SQL 语句这在表字段很多时依然是一项繁重的工作。1.2 MP 的出现懒人的福音与效率的飞跃MyBatis-Plus 的口号是只做增强不做改变这句话有两个层面的含义不改变兼容性它完全兼容 MyBatis。你原本习惯手写的 XML SQL、复杂的关联查询 (ResultMap)、动态 SQL 标签在引入 MP 后依然可以照常使用。MP 不会破坏你现有的工程结构。只增强生产力这是 MP 的杀手锏。它内置了通用的BaseMapper接口。以前的痛点哪怕只是写一个“根据 ID 查询用户”或“插入一个用户”你都需要先定义 Mapper 接口方法再去 XML 里写select或insert标签如果不小心把列名拼错了程序跑起来才会报错。现在的爽点你的 Mapper 接口只需要继承BaseMapper这就好比让你的接口“继承”了一个拥有标准 CRUD 能力的父类。MP 会在启动时自动帮你注入insert、deleteById、updateById、selectById等十几个通用方法的 SQL 实现。对于单表操作你真的一行 SQL 都不用写2. 代码中的核心知识点详解与避坑指南在阅读生成的 Java 代码前请先掌握以下核心概念这对应了代码中的关键部分。2.1 实体类 (Entity) 与 Lombok 的最佳实践在UserInfo.java中你会看到Data注解。知识点Lombok是一个在 Java 编译阶段生效的工具库。深层作用它不是在运行时通过反射生成代码而是利用 Java 的注解处理器Annotation Processing在代码编译成.class文件时自动“织入”了get、set、toString、hashCode、equals等方法的字节码。新手扩展为什么要用如果没有 Lombok一个拥有 10 个字段的UserInfo类其 Getter/Setter 代码可能占据 100 多行。这不仅让核心逻辑字段定义被淹没而且当你修改字段类型时比如把int改成Integer还需要手动去改下面的配套方法非常容易漏改。注意使用 Lombok 需要在 IDE如 IDEA中安装 Lombok 插件否则 IDE 无法识别这些自动生成的方法会提示代码报错。2.2 注解映射 (Mapping Annotations) —— MP 是如何“看懂”数据库的MP 如何知道 Java 类对应数据库哪张表靠的是约定大于配置的设计理念以及注解辅助。TableName(user_info):约定默认情况下MP 采用“驼峰转下划线”的规则。如果你的类名是UserInfoMP 会默认去数据库找user_info表。配置现实中数据库表名千奇百怪。如果表名是t_sys_user或者为了兼容旧系统叫tblUser这就破坏了约定。此时必须使用TableName(t_sys_user)显式告诉 MP“别猜了就是这张表”。TableId(主键策略):核心作用告诉 MP 哪个字段是主键。这至关重要因为updateById、deleteById等方法生成的WHERE子句完全依赖于此。深度扩展IdTypeIdType.AUTO数据库自增。依赖数据库本身的AUTO_INCREMENT特性。插入时 Java 传null数据库生成 ID 后MP 会自动把新 ID 回填到对象中。IdType.ASSIGN_ID(默认)雪花算法 (Snowflake)。这是 MP 默认的策略。即使你没配置自增MP 也会在内存中生成一个唯一的 19 位 Long 类型数字作为 ID。这在分布式系统中非常有用避免了数据库自增锁的性能瓶颈。TableField:字段名映射处理 Java 属性名 (userEmail) 和数据库列名 (email_addr) 不一致的情况。新手避坑exist false有时候你的实体类里需要一个辅助属性例如private String fullDescription用来在前端展示但数据库表中并没有这个列。此时必须加上TableField(exist false)否则 MP 在生成 SQL 时会试图去查full_description列导致报错Unknown column。2.3 BaseMapper 的泛型魔法在UserInfoMapper.java中这一行代码价值千金public interface UserInfoMapper extends BaseMapperUserInfo {}泛型UserInfo的意义:这是 MP 智能化的源头。你可能会问“为什么我什么都没写它就知道要查user_info表而不是order_info表”原理揭秘MP 在 Spring 启动阶段会通过 Java 反射机制解析UserInfoMapper父接口上的泛型参数。它拿到了UserInfo.class然后去扫描这个类上的TableName、TableField等注解。结果MP 就像一个动态的 SQL 拼装工厂它在内存中自动组装出了标准 SQL 语句如SELECT id, username... FROM user_info并将其注册到 MyBatis 的核心配置中。这就好比 MP 替你连夜写好了 XML 文件。3. 条件构造器 (Wrapper) - 代码中的重难点这是新手最容易晕也是 MP 最灵活、最强大的地方。当你需要摆脱简单的 ID 查询进行复杂条件筛选时Wrapper 就是你的 SQL 生成器。3.1 QueryWrapper (基础版 —— 并不推荐在生产环境大量使用)QueryWrapperUserInfo wrapper new QueryWrapper(); wrapper.eq(age, 18) .like(username, min) .or() .gt(age, 30);逻辑上述代码会被翻译成WHERE (age 18 AND username LIKE %min%) OR (age 30)。致命缺点魔法值你需要手动输入字符串age、username。场景演绎假设数据库管理员把age字段改成了user_age。你修改了 Java 实体类的属性名但你忘记或很难搜索到代码里所有散落的字符串age。编译时一切正常直到上线后用户点击查询程序直接崩溃报错Unknown column age。这被称为“魔法值炸弹”。3.2 LambdaQueryWrapper (进阶推荐版 —— 必须掌握)LambdaQueryWrapperUserInfo wrapper new LambdaQueryWrapper(); wrapper.eq(UserInfo::getAge, 18) .like(UserInfo::getUsername, min);知识点方法引用 (Method Reference)。UserInfo::getAge是 Java 8 引入的语法糖它本质上指向了属性本身。绝对优势编译期安全如果你手抖写成了UserInfo::getAgggeIDE 会立刻标红代码根本无法编译通过。这意味着你永远不会因为拼写错误而导致 SQL 运行失败。重构友好当你在 IDE 中使用重构功能Refactor - Rename将实体类的age属性改为userAge时所有使用UserInfo::getAge的地方都会自动同步修改。这是字符串硬编码绝对做不到的。新手建议除非是极其动态的场景列名本身就是变量否则请无脑选择 LambdaQueryWrapper4. 扩展知识点 (面试与实战必知)4.1 逻辑删除 (Logical Delete) —— 数据安全的安全带代码中出现了delete_flag。这是企业级开发中的标配。物理删除 (Physical Delete)执行DELETE FROM user WHERE id 1。数据从硬盘上彻底消失。如果员工手滑误删了重要数据除了去翻数据库备份可能是一天前的别无他法。逻辑删除 (Logical Delete)概念数据并没有真正消失只是被打上了“已删除”的标签。通常用0表示正常1表示删除。MP 的黑科技MP 提供了透明化的逻辑删除支持。你只需要在配置文件配置好逻辑删除字段或者在字段上加TableLogic注解。效果当你调用mapper.deleteById(1)时MP拦截了这个请求偷偷把它变成了UPDATE user SET delete_flag 1 WHERE id 1。当你调用mapper.selectById(1)或selectList时MP 会自动在 SQL 末尾追加AND delete_flag 0确保你查不到已删除的数据。价值既保证了业务上看数据删除了又保留了数据“尸体”用于审计、数据恢复或历史分析。4.2 自动填充 (Auto Fill) —— 告别重复劳动代码中有createTime和updateTime。痛点在传统的开发中每次写insert都要记得user.setCreateTime(new Date())每次update都要记得user.setUpdateTime(new Date())。只要有一处忘了数据库里就会出现null或旧时间导致数据不一致。扩展方案MP 提供了MetaObjectHandler接口。你可以创建一个配置类实现它告诉 MP“每当执行插入操作时帮我把createTime填上当前时间每当更新时帮我更新updateTime”。这样业务代码中再也不用出现时间设置的代码既干净又可靠。4.3 为什么不要在循环中调用数据库(N1 问题)在测试代码testSelectByIds中使用的是selectBatchIds批量查询。这是一个非常重要的性能知识点。错误示范 (新手常犯)ListLong ids Arrays.asList(1L, 2L, 3L, ..., 1000L); for (Long id : ids) { // 灾难现场在循环里调用 DAO/Mapper mapper.selectById(id); }后果推演网络开销每一次selectById都意味着一次【建立连接 - 发送 SQL - 数据库执行 - 返回结果 - 关闭连接/归还连接池】的全过程。如果 List 有 1000 个 ID你就与数据库进行了 1000 次网络交互。这比 SQL 执行本身慢得多。连接池耗尽高并发下这种代码会瞬间占满数据库连接池导致其他用户的请求被阻塞系统瘫痪。正确做法使用selectBatchIds。它会生成一条 SQLSELECT ... FROM ... WHERE id IN (1, 2, 3, ...)。效率1 次网络交互 vs 1000 次网络交互。效率提升是数量级的。5. 如何阅读接下来的代码看注释我为几乎每一行代码都添加了详细的//注释不仅解释这行代码在做什么还解释了为什么要这么写。关注 Import新手常忽略import部分导致自己写的时候找不到类。请特别留意com.baomidou.mybatisplus包下的类不要误引入了其他包的同名类。动手尝试代码中的testLambdaQueryWrapper是最精华的部分建议多读几遍体会链式调用的优雅。数据库初始化-- -------------------------------------------------------- -- 1. 创建数据库 -- IF EXISTS 是为了防止数据库已存在报错 -- DEFAULT CHARACTER SET utf8mb4 是为了支持 Emoji 表情等特殊字符 -- -------------------------------------------------------- DROP DATABASE IF EXISTS mybatis_test; CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4; -- 切换到刚创建的数据库 USE mybatis_test; -- -------------------------------------------------------- -- 2. 创建用户表 (user_info) -- -------------------------------------------------------- DROP TABLE IF EXISTS user_info; CREATE TABLE user_info ( id INT(11) NOT NULL AUTO_INCREMENT COMMENT 主键ID自增, username VARCHAR(127) NOT NULL COMMENT 用户名, password VARCHAR(127) NOT NULL COMMENT 密码, age TINYINT(4) NOT NULL COMMENT 年龄, gender TINYINT(4) DEFAULT 0 COMMENT 性别0-默认1-男2-女, phone VARCHAR(15) DEFAULT NULL COMMENT 手机号, delete_flag TINYINT(4) DEFAULT 0 COMMENT 逻辑删除标志0-正常1-已删除, create_time DATETIME DEFAULT NOW() COMMENT 创建时间默认当前时间, update_time DATETIME DEFAULT NOW() COMMENT 更新时间默认当前时间, PRIMARY KEY (id) ) ENGINEINNODB DEFAULT CHARSETutf8mb4 COMMENT用户表; -- -------------------------------------------------------- -- 3. 插入初始化测试数据 -- -------------------------------------------------------- INSERT INTO user_info (username, password, age, gender, phone) VALUES (admin, admin, 18, 1, 18612340001), (zhangsan, zhangsan, 18, 1, 18612340002), (lisi, lisi, 18, 1, 18612340003), (wangwu, wangwu, 18, 1, 18612340004);实体类package com.bite.mybatis.plus.entity; // 导入 Lombok 的注解用于自动生成 getter/setter/toString 等方法 import lombok.Data; // 导入 MyBatis-Plus 的注解 import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.IdType; import java.util.Date; /** * 实体类对应数据库中的表 user_info * * Data: Lombok 注解。 * 只要加了这个注解编译后会自动生成所有属性的: * getXXX(), setXXX(), toString(), equals(), hashCode() 方法。 * 省去了手动编写这些样板代码的麻烦。 * * TableName(user_info): MyBatis-Plus 注解。 * 告诉框架这个 UserInfo 类对应数据库里的 user_info 表。 * 如果不加这个注解MP 默认会把类名转换成下划线形式user_info去查找表 * 但显式写出来更清晰也防止类名修改后找不到表。 */ Data TableName(user_info) public class UserInfo { /** * TableId: 标识这是主键字段。 * value id: 对应数据库表中的列名 id。 * type IdType.AUTO: 指定主键生成策略。 * AUTO 代表数据库自增 (Auto Increment)。这意味着插入数据时 * Java 代码不需要设置 id 的值数据库会自动生成。 */ TableId(value id, type IdType.AUTO) private Integer id; // 使用 Integer 而不是 int因为 id 可能为 null (虽然主键一般不为空但在插入前是空的) // 用户名对应数据库 username 字段 private String username; // 密码对应数据库 password 字段 private String password; // 年龄 private Integer age; // 性别 private Integer gender; // 手机号 private String phone; /** * TableField(delete_flag): 映射非主键字段。 * 场景如果 Java 属性名叫 deleteFlag (驼峰)数据库列名叫 delete_flag (下划线) * MP 其实会自动映射。 * 但如果数据库列名叫 is_deleted属性名叫 deleteFlag就必须用此注解指定 * TableField(is_deleted) * * 这里显式写出来是为了演示该注解的用法。 */ TableField(delete_flag) private Integer deleteFlag; // 创建时间 private Date createTime; // 更新时间 private Date updateTime; }Mapper接口package com.bite.mybatis.plus.mapper; // 导入 MyBatis-Plus 的基础 Mapper 接口 import com.baomidou.mybatisplus.core.mapper.BaseMapper; // 导入注解和常量用于自定义 SQL import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.toolkit.Constants; import com.bite.mybatis.plus.entity.UserInfo; import java.util.List; /** * Mapper 接口 * * 1. Mapper: 这是 Spring/MyBatis 的注解标记这是一个 Mapper 组件 * Spring Boot 启动时会扫描到它并创建代理对象注入到容器中。 * * 2. extends BaseMapperUserInfo: 这是 MP 最核心的用法 * 继承了 BaseMapper并指定泛型为 UserInfo。 * 结果UserInfoMapper 瞬间自动拥有了针对 UserInfo 表的 * insert, delete, update, select 等一系列 CRUD 方法。 * 不需要写任何 XML也不需要写任何实现类。 */ Mapper public interface UserInfoMapper extends BaseMapperUserInfo { // // 以下是 PDF 3.4 节提到的 自定义 SQL 示例 // 当 MP 内置的方法满足不了极其复杂的业务需求时我们可以结合 Wrapper 和手写 SQL // /** * 示例 1: 使用注解方式自定义查询 * * ${ew.customSqlSegment}: * ew 是 EntityWrapper 的缩写参数名必须叫 ew 或者用 Param 指定。 * customSqlSegment 是 Wrapper 对象根据你 Java 代码生成的 SQL 片段例如 WHERE age 18。 * 注意这里用的是 ${} 进行字符串拼接因为 Wrapper 生成的是 SQL 关键字不能用 #{} 预编译。 */ Select(select id, username, password, age FROM user_info ${ew.customSqlSegment}) ListUserInfo queryUserByCustom(Param(Constants.WRAPPER) WrapperUserInfo wrapper); /** * 示例 2: 对应 XML 配置方式 (假设有 XML 文件) * 这里只定义接口XML 内容请参考 PDF 页面 16 */ ListUserInfo queryUserByCustom2(Param(Constants.WRAPPER) WrapperUserInfo wrapper); /** * 示例 3: 自定义更新 SQL * * 场景把某些用户的年龄增加指定的值 (age age ?)。 * MP 内置的 update 主要是覆盖值这种基于原值的运算适合自定义 SQL。 * * #{addAge}: 这是一个普通参数会被预编译成 ?防止 SQL 注入。 * ${ew.customSqlSegment}: 这是 Wrapper 生成的条件部分 (例如 WHERE id IN (1,2,3))。 */ Update(UPDATE user_info SET age age #{addAge} ${ew.customSqlSegment}) void updateUserByCustom(Param(addAge) int addAge, Param(Constants.WRAPPER) WrapperUserInfo wrapper); }测试类(核心逻辑)package com.bite.mybatis.plus; // 导入测试相关的类 import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; // 导入 MP 的条件构造器 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; // 导入我们的实体和 Mapper import com.bite.mybatis.plus.entity.UserInfo; import com.bite.mybatis.plus.mapper.UserInfoMapper; import java.util.List; import java.util.Arrays; // 注意PDF里用了 List.of (Java 9)这里兼容性起见可能用到 Arrays.asList /** * 单元测试类 * * SpringBootTest: 启动 Spring Boot 上下文。 * 这样我们可以使用 Autowired 注入 Mapper像在真实的 Controller 里一样运行代码。 */ SpringBootTest class MybatisPlusDemoApplicationTests { // 依赖注入将 Spring 容器管理的 UserInfoMapper 实例注入进来 Autowired private UserInfoMapper userInfoMapper; // // 2.3 基础 CRUD 测试 (对应 PDF 第 6 页) // /** * 测试插入 (Insert) * MP 会自动根据实体类属性生成 SQL: INSERT INTO user_info (username, ...) VALUES (...) */ Test void testInsert() { System.out.println(----- 测试插入 -----); UserInfo user new UserInfo(); user.setUsername(bite); // 设置用户名 user.setPassword(123456); // 设置密码 user.setAge(11); user.setGender(0); user.setPhone(18610001234); // 注意我们没有设置 ID因为配置了 AUTO 自增数据库会处理 // 调用 BaseMapper 提供的 insert 方法 int result userInfoMapper.insert(user); // 扩展知识插入成功后MP 会自动把数据库生成的 ID 回填到 user 对象中 System.out.println(影响行数: result); System.out.println(插入后的主键ID: user.getId()); } /** * 测试根据 ID 查询 */ Test void testSelectById() { System.out.println(----- 测试根据 ID 查询 -----); // 这里的 1L 表示 Long 类型或者直接写 1 UserInfo user userInfoMapper.selectById(1); System.out.println(查询结果: user); } /** * 测试批量查询 ID (WHERE id IN (...)) */ Test void testSelectByIds() { System.out.println(----- 测试批量查询 -----); // List.of 是 Java 9 语法如果报错请换成 Arrays.asList(1, 2, 3, 4) ListInteger ids Arrays.asList(1, 2, 3, 4); ListUserInfo users userInfoMapper.selectBatchIds(ids); // 使用 Lambda 表达式打印结果 users.forEach(System.out::println); } /** * 测试根据 ID 更新 * 注意MP 的 updateById 是动态 SQL它只会更新你设置了非空值的字段。 * 如果你只 setPasswordSQL 就只会 UPDATE ... SET password ? ... * 这里的 age、phone 等其他字段不会被修改为 null。 */ Test void testUpdateById() { System.out.println(----- 测试更新 -----); UserInfo user new UserInfo(); user.setId(1); // 必须指定 ID否则 MP 不知道更新哪条 user.setPassword(4444444); // 只更新密码 userInfoMapper.updateById(user); } /** * 测试根据 ID 删除 */ Test void testDelete() { System.out.println(----- 测试删除 -----); userInfoMapper.deleteById(5); // 删除 ID 为 5 的记录 } // // 3.3 条件构造器测试 (Wrapper) - 重点知识 // /** * 3.3.1 QueryWrapper (普通查询构造器) * 需求SELECT ... WHERE age 18 AND username LIKE %min% */ Test void testQueryWrapper() { System.out.println(----- QueryWrapper 测试 -----); QueryWrapperUserInfo wrapper new QueryWrapper(); // 链式调用 wrapper.select(id, username, password, age) // 指定查询哪些列不查全部 .eq(age, 18) // eq: equal (等于) - age 18 .like(username, min); // like: 模糊查询 - username like %min% ListUserInfo userInfos userInfoMapper.selectList(wrapper); userInfos.forEach(System.out::println); } /** * QueryWrapper 用于更新 * 需求UPDATE user_info SET delete_flag 1 WHERE age 20 */ Test void testUpdateByQueryWrapper() { System.out.println(----- QueryWrapper 更新测试 -----); // 1. 定义更新的条件 (WHERE age 20) QueryWrapperUserInfo wrapper new QueryWrapper(); wrapper.lt(age, 20); // lt: less than (小于) // 2. 定义要更新成什么样 (SET delete_flag 1) UserInfo userInfo new UserInfo(); userInfo.setDeleteFlag(1); // 执行把符合 wrapper 条件的数据更新为 userInfo 里的样子 userInfoMapper.update(userInfo, wrapper); } /** * 3.3.2 UpdateWrapper (专门用于更新的构造器) * 场景不创建 UserInfo 实体对象直接设置 SET 语句 * 需求UPDATE user_info SET delete_flag0, age5 WHERE id IN (1,2,3) */ Test void testUpdateByUpdateWrapper() { System.out.println(----- UpdateWrapper 测试 -----); UpdateWrapperUserInfo updateWrapper new UpdateWrapper(); updateWrapper.set(delete_flag, 0) // 显式设置 SET 字段 .set(age, 5) .in(id, Arrays.asList(1, 2, 3)); // WHERE id IN ... userInfoMapper.update(null, updateWrapper); // 第一个参数传 null因为 Set 子句已经在 wrapper 里了 } /** * UpdateWrapper 执行 SQL 片段 * 需求UPDATE user_info SET age age 10 WHERE id IN (1,2,3) */ Test void testUpdateBySQLUpdateWrapper() { System.out.println(----- UpdateWrapper SQL 片段测试 -----); UpdateWrapperUserInfo updateWrapper new UpdateWrapper(); updateWrapper.setSql(age age 10) // 直接拼接 SQL 片段适合做数学运算 .in(id, Arrays.asList(1, 2, 3)); userInfoMapper.update(null, updateWrapper); } // // 3.3.3 LambdaQueryWrapper (推荐使用) // 优点防手抖。不用写 age 字符串而是用 UserInfo::getAge 方法引用。 // 如果实体类属性名改了这里会自动报错而不是运行时才报错。 // Test void testLambdaQueryWrapper() { System.out.println(----- LambdaQueryWrapper 测试 (强力推荐) -----); // 写法 1new 对象 // LambdaQueryWrapperUserInfo lambda new LambdaQueryWrapper(); // 写法 2通过 QueryWrapper 转 lambda (更常用) QueryWrapperUserInfo wrapper new QueryWrapper(); ListUserInfo list userInfoMapper.selectList(wrapper.lambda() .select(UserInfo::getUsername, UserInfo::getPassword, UserInfo::getAge) // 看着很长但全是IDE自动补全的很安全 .eq(UserInfo::getId, 1) // WHERE id 1 ); list.forEach(System.out::println); } /** * 3.3.4 LambdaUpdateWrapper */ Test void testLambdUpdateByUpdateWrapper() { System.out.println(----- LambdaUpdateWrapper 测试 -----); LambdaUpdateWrapperUserInfo updateWrapper new LambdaUpdateWrapper(); updateWrapper.set(UserInfo::getDeleteFlag, 0) // SET delete_flag 0 .set(UserInfo::getAge, 5) // SET age 5 .in(UserInfo::getId, Arrays.asList(1, 2, 3)); // WHERE id IN (1,2,3) userInfoMapper.update(null, updateWrapper); } // // 3.4 自定义 SQL 测试 // Test void testQueryUserByCustom() { System.out.println(----- 自定义 SQL 测试 -----); QueryWrapperUserInfo wrapper new QueryWrapper(); wrapper.eq(username, admin); // 调用 Mapper 中我们自己定义的 queryUserByCustom 方法 // 此时 wrapper 生成的 SQL 会自动填充到 ${ew.customSqlSegment} 中 ListUserInfo result userInfoMapper.queryUserByCustom(wrapper); result.forEach(System.out::println); } Test void updateUserByCustom() { System.out.println(----- 自定义 Update SQL 测试 -----); QueryWrapperUserInfo wrapper new QueryWrapper(); wrapper.in(id, Arrays.asList(1, 2, 3)); // 将年龄统一增加 10 岁 userInfoMapper.updateUserByCustom(10, wrapper); } }以上为您生成了完整的学习资料建议您按照 Guide 文档 - 实体类 - Mapper - 测试类 的顺序阅读祝您学习愉快为了让你能顺利运行我为你补充了3 个必不可少的配置文件pom.xml:项目的“购物清单”。告诉 Maven 我们需要下载 Spring Boot、MyBatis-Plus、MySQL 驱动等所有依赖。application.yml:项目的“遥控器”。配置你的数据库账号密码。MybatisPlusApplication.java:项目的“启动钥匙”。Spring Boot 的主启动类。README_Run_Guide.md:保姆级运行手册。一步步教你在 IDEA 里怎么操作。请按照下面的README 手册一步步操作保证能跑通如何运行本项目 (保姆级教程).mdMyBatis-Plus 实战项目运行指南你好请按照以下步骤在你的电脑桌面上搭建并运行这个项目。第一步环境准备 (必看)在开始之前请确保你的电脑安装了以下软件JDK: 推荐 JDK 17 或 JDK 8。IntelliJ IDEA: 推荐使用社区版 (Community) 或 旗舰版 (Ultimate)。MySQL 数据库: 确保数据库服务已开启且记得你的账号和密码。Maven: 通常 IDEA 自带了 Maven不需要额外安装。第二步搭建工程骨架新建文件夹:在桌面上新建一个文件夹命名为mybatis-plus-demo。用 IDEA 打开:启动 IDEA点击Open(打开)选择桌面上的mybatis-plus-demo文件夹。创建标准目录结构:在 IDEA 左侧的项目栏中右键点击项目名按照以下结构新建文件夹Directorymybatis-plus-demo ├── src │ ├── main │ │ ├── java │ │ │ └── com │ │ │ └── bite │ │ │ └── mybatis │ │ │ └── plus │ │ │ ├── entity (存放 UserInfo.java) │ │ │ └── mapper (存放 UserInfoMapper.java) │ │ └── resources (存放 application.yml) │ └── test │ └── java │ └── com │ └── bite │ └── mybatis │ └── plus (存放 MybatisPlusTests.java) └── pom.xml (直接放在最外层)第三步复制文件 (核心步骤)请将我生成的代码复制到对应的位置pom.xml:在项目最外层新建pom.xml文件。复制我刚才提供的pom.xml代码进去。重要复制完后点击 IDEA 右上角出现的一个小图标类似于“M”形状的刷新按钮或者右键pom.xml选择Maven-Reload Project。这会自动下载依赖包需要联网。application.yml:在src/main/resources目录下新建application.yml。复制代码进去。修改密码找到password: root这一行把root改成你本地 MySQL 的真实密码(如果是空密码就留空但通常不建议)。Java 代码:UserInfo.java: 放入src/main/java/com/bite/mybatis/plus/entityUserInfoMapper.java: 放入src/main/java/com/bite/mybatis/plus/mapperMybatisPlusApplication.java: 放入src/main/java/com/bite/mybatis/plus(这是启动类放在包的最外层)MybatisPlusTests.java: 放入src/test/java/com/bite/mybatis/plus第四步初始化数据库打开你的数据库工具如 MySQL Workbench, Navicat, DBeaver, 或 IDEA 自带的 Database 面板。复制我提供的schema.sql文件的内容。执行 SQL全选并在数据库中运行。这会创建名为mybatis_test的数据库。创建user_info表。插入 4 条初始数据。第五步运行测试现在是最激动人心的时刻打开src/test/java/.../MybatisPlusTests.java文件。你会看到很多Test标记的方法比如testInsert(),testSelectById()。点击运行点击方法名左边的小绿三角 ▶️选择Run testInsert()。观察控制台IDEA 下方的控制台会打印出日志。如果是testInsert你会看到Insert语句和“插入成功”的日志。如果是testSelectById你会看到查询到的 User 对象。恭喜你你已经成功运行了一个企业级的 MyBatis-Plus 项目Maven配置文件?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion !-- Spring Boot 父工程帮我们管理版本号 -- parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.2.0/version !-- 推荐使用较新的稳定版 -- relativePath/ /parent groupIdcom.bite/groupId artifactIdmybatis-plus-demo/artifactId version0.0.1-SNAPSHOT/version namemybatis-plus-demo/name descriptionMyBatis-Plus 新手实战项目/description properties java.version17/java.version !-- 这里的版本要和你电脑安装的JDK版本一致如果是JDK8就写1.8 -- /properties dependencies !-- 1. Spring Boot Web 启动器 (虽然我们是测试但习惯加上) -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- 2. MyBatis-Plus 核心依赖 (包含 MyBatis) -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-spring-boot3-starter/artifactId version3.5.5/version /dependency !-- 3. MySQL 驱动 (连接数据库用) -- dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependency !-- 4. Lombok (简化代码工具) -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- 5. 测试依赖 (JUnit 等) -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies build plugins !-- Spring Boot 打包插件 -- plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId configuration excludes exclude groupIdorg.projectlombok/groupId artifactIdlombok/artifactId /exclude /excludes /configuration /plugin /plugins /build /project数据库配置# 数据库连接配置 spring: datasource: # 数据库驱动新版 MySQL 驱动类名 driver-class-name: com.mysql.cj.jdbc.Driver # 数据库 URL # jdbc:mysql://IP地址:端口/数据库名 # useSSLfalse: 关闭 SSL 安全连接开发环境通常关闭以避免报错 # serverTimezoneAsia/Shanghai: 设置时区防止时间差 8 小时 # allowPublicKeyRetrievaltrue: 允许公钥检索解决某些连接错误 url: jdbc:mysql://127.0.0.1:3306/mybatis_test?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue # 数据库账号 username: root # 数据库密码 【请修改这里为你自己的密码】 password: root # MyBatis-Plus 配置 mybatis-plus: configuration: # 开启控制台 SQL 日志打印 # 这样你运行测试时控制台会打印出实际执行的 SQL 语句非常适合学习 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: # 逻辑删除配置1 表示已删除0 表示未删除 logic-delete-value: 1 logic-not-delete-value: 0Spring Boot启动类package com.bite.mybatis.plus; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** * 项目的启动类 * SpringBootApplication: 标记这是一个 Spring Boot 应用 * MapperScan: 扫描 Mapper 接口所在的包 * 告诉 MP 去哪里找我们定义的 UserInfoMapper。 * 如果不加这个注解或者包路径写错了会报错 Field userInfoMapper in ... required a bean of type ... */ SpringBootApplication MapperScan(com.bite.mybatis.plus.mapper) public class MybatisPlusApplication { public static void main(String[] args) { SpringApplication.run(MybatisPlusApplication.class, args); } }好的所有的材料都准备齐全了。请按照README_Run_Guide.md中的步骤开始你的实战之旅吧如果在运行过程中遇到任何红色报错随时把报错信息发给我我来帮你诊断。加油太棒了Exit code 0代表程序完美运行没有任何报错。恭喜你你已经正式跨过了 MyBatis-Plus 的门槛这不仅仅是一堆日志这其实是 MyBatis-Plus (MP) 在向你汇报工作。这个项目通过一系列测试模拟了真实开发中对数据库的各种操作。让我们像看“体检报告”一样根据你控制台打印出的日志一条条解读这个项目到底干了啥1. 批量修改数据 (UpdateWrapper)日志证据Plaintext----- UpdateWrapper 测试 ----- Preparing: UPDATE user_info SET delete_flag?,age? WHERE (id IN (?,?,?)) Parameters: 0(Integer), 5(Integer), 1(Integer), 2(Integer), 3(Integer) Updates: 3解读MP 帮你把 ID 为 1, 2, 3 的用户一次性把delete_flag改为了 0age改为了 5。牛逼之处你没写WHERE id IN这种复杂的 SQL是 Java 代码自动生成的。2. 数学运算更新 (SQL 片段)日志证据Plaintext----- UpdateWrapper SQL 片段测试 ----- Preparing: UPDATE user_info SET age age 10 WHERE (id IN (?,?,?))解读它给 ID 为 1, 2, 3 的用户年龄统统加了 10 岁。这展示了 MP 允许你在自动生成的 SQL 里夹带“私货”自定义 SQL 片段。3. 单条更新 (UpdateById)日志证据Plaintext----- 测试更新 ----- Preparing: UPDATE user_info SET password? WHERE id? Parameters: 4444444(String), 1(Integer)解读专门把 ID 为 1 的用户admin的密码改成了 4444444。注意它只更新了密码其他字段没动这就是“动态 SQL”的智能之处。4. 精准查询 (LambdaQueryWrapper)日志证据Plaintext----- LambdaQueryWrapper 测试 (强力推荐) ----- Preparing: SELECT username,password,age FROM user_info WHERE (id ?)解读它去数据库查了 ID 为 1 的用户但只取了用户名、密码和年龄这三个字段没取别的。这是一种优化性能的查询方式。5. 批量查询 (SelectByIds)日志证据Plaintext----- 测试批量查询 ----- Preparing: SELECT ... FROM user_info WHERE id IN ( ? , ? , ? , ? ) Row: 1, admin... Row: 2, zhangsan... Total: 4解读一次性把 ID 为 1, 2, 3, 4 的四个用户全查出来了。这避免了你写循环去查库N1 问题。6. 条件更新 (QueryWrapper)日志证据Plaintext----- QueryWrapper 更新测试 ----- Preparing: UPDATE user_info SET delete_flag? WHERE (age ?) Parameters: 1(Integer), 20(Integer) Updates: 4解读它执行了一个业务逻辑——把所有“年龄小于 20 岁”的用户delete_flag标记为 1逻辑删除。日志显示有 4 个人符合条件被修改了。7. 删除操作 (Delete)日志证据Plaintext----- 测试删除 ----- Preparing: DELETE FROM user_info WHERE id? Parameters: 5(Integer) Updates: 0解读它尝试删除 ID 为 5 的用户。注意这里显示Updates: 0说明删除失败了没删掉任何行。为什么因为代码运行顺序的问题ID 为 5 的用户在这一步还没被插入呢看下一步8. 插入新用户 (Insert)日志证据Plaintext----- 测试插入 ----- Preparing: INSERT INTO user_info ( username, ... ) VALUES ( ?, ... ) Parameters: bite(String), ... Updates: 1 插入后的主键ID: 5解读成功向数据库插入了一个叫 bite 的新用户。数据库自动给它分配了 ID5。(所以如果在 测试删除 之前运行这一步删除就会成功了) 总结这个项目通过实战向你展示了 MyBatis-Plus 的核心价值观极简主义你没有手写一句INSERT、UPDATE或SELECT语句但完成了所有复杂的增删改查。安全性所有的参数比如admin18都通过?占位符传递防止了 SQL 注入攻击。灵活性既能全自动BaseMapper也能半自动Wrapper 组装条件还能搞特权自定义 SQL。现在的你已经拥有了一个可以随时用来实验数据库操作的“演武场”这是一个非常棒的问题你现在遇到的情况是代码运行速度太快几毫秒就跑完了就像一阵风刮过你还没来得及眨眼数据库里的数据可能已经经历了“插入 - 修改 - 删除”的一生。要想亲眼看到数据变化的路径比如先变出一条数据然后年龄变了最后消失了你需要让时间“慢下来”或者让程序“停下来”等你查岗。这里有三种方法推荐程度由高到低强烈推荐方法一方法一使用 IDEA 的“断点调试” (Debug 模式) —— 上帝视角 ️‍♂️这是程序员最常用的方法就像给程序按下了“暂停键”。操作步骤打断点 (红点)打开你的MybatisPlusTests.java。找到testUpdateById方法。在userInfoMapper.updateById(user);这一行的行号左边用鼠标左键点一下。你会看到一个 红色的圆点。这就是断点。启动调试 (Debug)不要点绿色三角形的 Run。要点绿色三角形旁边那个 虫子图标 (Debug)。或者右键方法名选择Debug testUpdateById()。观察变化程序运行到红点处会自动卡住暂停。此时动作 1切换到你的数据库软件Navicat / DBeaver / IDEA Database刷新表user_info。你会发现数据还没变。此时动作 2回到 IDEA按一下F8(Step Over) 或者点击调试面板上的折线箭头步过。这代表让程序执行这一行代码。此时动作 3再次切换到数据库软件刷新表。见证奇迹数据变了通过这种方式你可以一步步控制代码执行每走一步就去数据库看一眼完全掌握数据变化的每一个瞬间。方法二手动“单步执行” —— 稳扎稳打 如果你觉得 Debug 有点复杂可以笨办法不要运行整个类而是手动一个个运行方法并配合数据库刷新。前提先去数据库执行TRUNCATE TABLE user_info;把表清空或者恢复到初始状态。操作步骤第一步只运行插入找到testInsert方法。点击左边绿色箭头 -Run testInsert().看数据库刷新你会看到多了一行数据假设 ID 是 5。第二步只运行更新找到testUpdateById方法。关键修改把代码里的user.setId(1)改成刚才插入的 ID比如user.setId(5)。点击左边绿色箭头 -Run testUpdateById().看数据库刷新ID 为 5 的用户密码变了。第三步只运行删除找到testDelete方法。修改 ID 为 5。运行 -看数据库刷新ID 为 5 的用户delete_flag变成了 1逻辑删除或者行消失了物理删除。方法三在代码里“强行睡觉” (不推荐但直观) 你可以强行让代码执行完一步后睡个 10 秒钟给你留出刷新数据库的时间。操作步骤修改你的测试代码加上Thread.sleepJavaTest void testLifeCycle() throws InterruptedException { // 1. 插入 UserInfo user new UserInfo(); user.setUsername(Flash); user.setAge(20); user.setPassword(123); userInfoMapper.insert(user); System.out.println( 插入完成快去数据库看给你10秒钟...); Thread.sleep(10000); // 暂停 10 秒 // 2. 更新 user.setAge(99); userInfoMapper.updateById(user); System.out.println( 更新完成快去数据库看给你10秒钟...); Thread.sleep(10000); // 暂停 10 秒 // 3. 删除 userInfoMapper.deleteById(user.getId()); System.out.println( 删除完成去看看还在不在); }运行这个方法你就有 10 秒钟的时间切屏去数据库刷新查看变化了。 总结建议作为新手我强烈建议你尝试方法一Debug 模式。虽然它看起来有点高级但这是程序员最核心的技能之一。学会了 Debug你不仅能看到数据的变化路径以后遇到 Bug 也能看到程序是怎么“跑偏”的。现在去试着在一个update语句上打个红点然后点那个 虫子图标试试吧
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

做优惠卷网站倒闭了多少钱鑫牛元网站建设

Obsidian美化资源极速获取:国内镜像加速全攻略 【免费下载链接】awesome-obsidian 🕶️ Awesome stuff for Obsidian 项目地址: https://gitcode.com/gh_mirrors/aw/awesome-obsidian 当你打开Obsidian准备整理笔记时,是否曾经遇到过这…

张小明 2026/1/10 17:18:33 网站建设

做网站图片多少钱seo招聘的关键词

实验需求: 1.按照图示配置IP地址,公网地址100.1.1.1/24 2.私网A通过NAPT,使R1接入到互联网,私网B通过EASY IP,使R3接入到互联网 3.私网A配置NAT SERVER把Telnet的Telnet服务发布到公网,使PC2可以访问1、配置IP地址 [Te…

张小明 2026/1/10 10:04:33 网站建设

九江做网站的大公司一键安装网站运行环境

17.2 Agent工作流:构建智能决策系统 在上一节中,我们探讨了如何将模型工程化为稳定服务。今天,我们将深入研究Agent工作流技术,这是构建智能决策系统的核心技术之一。Agent工作流能够让AI系统具备更强的自主性和决策能力,实现复杂的业务流程自动化。 Agent工作流概述 A…

张小明 2026/1/10 20:04:23 网站建设

小程序源码怎么搭建宁波seo怎么做优化公司

文章目录openpnp - Smoothieware - MKS SGEN_L V1.0 JLink-edu-mini 连接测试概述笔记用JLink官方软件来测试板子电源调试接口的连接转接板和JLink-edu-mini的连接确定杜邦线的颜色转接板到板子SWD端子排的连接转接板端板子上的SWD接口排针用JLINK软件测试ENDopenpnp - Smooth…

张小明 2026/1/11 20:23:29 网站建设

手机网站建设域名空间手机怎么做弹幕小视频网站

CSS变量(自定义属性):在现代CSS中的深度应用与革新实践 CSS变量(Custom Properties)作为现代前端开发的核心特性之一,自2015年正式纳入CSS规范以来,已彻底改变了传统CSS的硬编码模式。通过引入变…

张小明 2026/1/10 20:42:37 网站建设

做文件的网站重庆移动网站制作

音视频编解码库终极指南:解锁多媒体开发新高度 【免费下载链接】avcodec-58.zip资源文件下载 avcodec-58.zip 资源文件下载本仓库提供了一个名为 avcodec-58.zip 的资源文件下载 项目地址: https://gitcode.com/open-source-toolkit/9bd65 还在为音视频处理性…

张小明 2026/1/26 13:40:34 网站建设