当前位置: 首页 > news >正文

MyBatis 的 新增、修改、删除 操作

一、准备工作回顾

  • 项目类型:Spring Boot 非 Web 应用
  • 数据库:MySQL(表结构沿用前文的 user 表)
  • 映射方式:XML 文件(更灵活,支持复杂 SQL)
  • 测试方式:CommandLineRunner 或单元测试

表结构(简化版):

CREATE TABLE user (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50),email VARCHAR(100)
);

二、实体类与 Mapper 接口

1. User 实体类

// src/main/java/com/example/mybatisdemo/model/User.java
package com.example.mybatisdemo.model;public class User {private Integer id;private String name;private String email;// 构造函数(可选)public User() {}public User(String name, String email) {this.name = name;this.email = email;}// Getters & Setterspublic Integer getId() { return id; }public void setId(Integer id) { this.id = id; }public String getName() { return name; }public void setName(String name) { this.name = name; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }@Overridepublic String toString() {return "User{id=" + id + ", name='" + name + "', email='" + email + "'}";}
}

2. UserMapper 接口(定义 CRUD 方法)

// src/main/java/com/example/mybatisdemo/mapper/UserMapper.java
package com.example.mybatisdemo.mapper;import com.example.mybatisdemo.model.User;
import org.apache.ibatis.annotations.Mapper;import java.util.List;@Mapper
public interface UserMapper {// 查询List<User> findAll();User findById(Integer id);// 新增int insert(User user);                          // 普通插入int insertSelective(User user);                // 选择性插入(非空字段)// 修改int updateById(User user);                    // 全量更新int updateSelectiveById(User user);           // 选择性更新// 删除int deleteById(Integer id);int deleteByIds(List<Integer> ids);           // 批量删除
}

三、XML 映射文件详解(UserMapper.xml

路径:src/main/resources/mapper/UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.mybatisdemo.mapper.UserMapper"><!-- 查询 --><select id="findAll" resultType="com.example.mybatisdemo.model.User">SELECT id, name, email FROM user</select><select id="findById" resultType="User" parameterType="int">SELECT id, name, email FROM user WHERE id = #{id}</select><!-- 1. 新增:全字段插入 --><insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id">INSERT INTO user (name, email)VALUES (#{name}, #{email})</insert><!-- 2. 新增:选择性插入(仅插入非 null 字段) --><insert id="insertSelective" parameterType="User" useGeneratedKeys="true" keyProperty="id">INSERT INTO user<trim prefix="(" suffix=")" suffixOverrides=","><if test="name != null">name,</if><if test="email != null">email,</if></trim><trim prefix="VALUES (" suffix=")" suffixOverrides=","><if test="name != null">#{name},</if><if test="email != null">#{email},</if></trim></insert><!-- 3. 修改:全量更新 --><update id="updateById" parameterType="User">UPDATE userSET name = #{name}, email = #{email}WHERE id = #{id}</update><!-- 4. 修改:选择性更新(只更新非 null 字段) --><update id="updateSelectiveById" parameterType="User">UPDATE user<set><if test="name != null">name = #{name},</if><if test="email != null">email = #{email},</if></set>WHERE id = #{id}</update><!-- 5. 删除:单条 --><delete id="deleteById" parameterType="int">DELETE FROM user WHERE id = #{id}</delete><!-- 6. 删除:批量(使用 foreach) --><delete id="deleteByIds" parameterType="java.util.List">DELETE FROM user WHERE id IN<foreach collection="list" item="id" open="(" close=")" separator=",">#{id}</foreach></delete></mapper>

🔍 关键标签说明:

标签/属性作用
useGeneratedKeys="true"启用数据库自动生成主键(如 MySQL 的 AUTO_INCREMENT)
keyProperty="id"将生成的主键回填到实体类的 id 字段
<trim>动态拼接 SQL,避免多余逗号
<set>用于 UPDATE,自动处理 SET 子句末尾的逗号
<foreach>遍历集合,常用于 IN 查询或批量操作

四、在非 Web 环境中测试 CRUD

方式一:使用 CommandLineRunner

// 在主启动类中添加
@Bean
public CommandLineRunner crudTest(UserMapper userMapper) {return args -> {System.out.println("=== 1. 新增用户 ===");User user = new User("Tom", "tom@example.com");userMapper.insert(user);System.out.println("插入后 ID: " + user.getId());System.out.println("\n=== 2. 查询所有 ===");userMapper.findAll().forEach(System.out::println);System.out.println("\n=== 3. 修改用户 ===");user.setEmail("tom_new@example.com");userMapper.updateById(user);System.out.println("更新后的用户: " + userMapper.findById(user.getId()));System.out.println("\n=== 4. 选择性新增(仅 name)===");User partialUser = new User();partialUser.setName("PartialUser");// email 为 null,不会插入userMapper.insertSelective(partialUser);System.out.println("部分插入结果: " + partialUser);System.out.println("\n=== 5. 批量删除 ===");List<Integer> idsToDelete = Arrays.asList(partialUser.getId(), user.getId());int deleted = userMapper.deleteByIds(idsToDelete);System.out.println("删除记录数: " + deleted);};
}

记得导入:

import java.util.Arrays;

方式二:JUnit 单元测试(推荐用于验证逻辑)

// src/test/java/com/example/mybatisdemo/UserCrudTest.java
@SpringBootTest
public class UserCrudTest {@Autowiredprivate UserMapper userMapper;@Testvoid testInsertAndUpdate() {// 插入User u = new User("JUnit", "junit@test.com");userMapper.insert(u);assertThat(u.getId()).isNotNull();// 修改u.setName("Updated JUnit");userMapper.updateById(u);User updated = userMapper.findById(u.getId());assertThat(updated.getName()).isEqualTo("Updated JUnit");// 删除userMapper.deleteById(u.getId());assertThat(userMapper.findById(u.getId())).isNull();}@Testvoid testInsertSelective() {User u = new User();u.setName("OnlyName");// email 为 nulluserMapper.insertSelective(u);assertThat(u.getId()).isNotNull();User saved = userMapper.findById(u.getId());assertThat(saved.getEmail()).isNull(); // 确保 email 未写入userMapper.deleteById(u.getId());}
}

五、注意事项与最佳实践

✅ 主键回填

  • 必须设置 useGeneratedKeys="true" 和 keyProperty
  • 适用于自增主键(MySQL、SQL Server),Oracle 需用 <selectKey>

✅ 选择性操作(避免覆盖 null)

  • 使用 <if> 判断字段是否为 null
  • 防止 update 把已有数据设为 null

✅ 批量操作性能

  • 批量插入可用 <foreach> + INSERT INTO ... VALUES (...), (...), ...
  • 但注意 SQL 长度限制(MySQL max_allowed_packet

✅ 事务控制(重要!)

若需保证多个操作原子性,加上 @Transactional

@Service
public class UserService {@Autowiredprivate UserMapper userMapper;@Transactionalpublic void batchOperation() {userMapper.insert(new User("A", "a@test.com"));userMapper.insert(new User("B", "b@test.com"));// 若中间出错,全部回滚}
}

并在主类启用事务:

@SpringBootApplication
@EnableTransactionManagement // 启用事务(Spring Boot 通常自动开启,但显式声明更安全)
public class MybatisDemoApplication { ... }

六、总结

操作XML 标签关键技巧
新增<insert>useGeneratedKeys + keyProperty
修改<update><set> + <if> 实现选择性更新
删除<delete><foreach> 支持批量
安全使用选择性操作避免 null 覆盖
可靠结合 @Transactional 保证数据一致性
http://www.dtcms.com/a/614458.html

相关文章:

  • 2025年计算机行情如何,有哪些方向可以入坑
  • C语言编译器优化技术研究
  • 鸿蒙PC平台三方库移植实战:以libid3tag库为例(附完整移植流程)
  • 国际企业网站建设请人做网站需要注意什么
  • 网站建设平台设备知名互联网公司有哪些
  • 使用62256为8051单片机扩展SRAM(使用proteus仿真)
  • LeetCode 刷题【155. 最小栈】
  • 零售场景下的数智店商:解决盗损问题,化解隐性成本痛点
  • 做网站 计算机有交嘛一个thinkphp搭建的微网站
  • 郑州炫彩网站建设企业网站的建设与实现
  • 网站建设外文文献湖南省建设厅证件查询
  • 综合练习-02
  • 《Multimodal Machine Learning: A Survey and Taxonomy》论文主要内容
  • 设计师网站有哪些郑州抖音seo推广
  • 爪哇周赛 Round 1
  • 如何做双版网站查询网138网站域名
  • 常州建设工程监理员挂证网站上网站建设
  • [C++]拷贝构造函数使用规则以及注意事项
  • 针对RK3506J 开发嵌入式固件架构选型:RT-Thread SMP 与 Linux 部署方案对比
  • 襄阳教育云平台网站建设长沙seo优化推广
  • 10.2 MCP三驾马车:Prompts、Resources、Tools详解
  • Hilbert空间中随机变量的一点几何直觉
  • 网站制作费用贵不贵wordpress 视频
  • 深入 Linux 内核启动:从按下电源到用户登录的全景解剖
  • 建设环保网站查询系统天猫商家入驻需要什么条件
  • Java中的异常体系详解:深度解析与代码示例
  • 浙江邮电工程建设有限公司网站湖南长沙怎么注册工作室
  • 河南单位网站建设金坛网站制作
  • 红黑树进阶封装实现C++_map_set(源码剖析)
  • 服装设计手稿设计图外贸网站优化谷歌关键词排名