欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 美景 > 第二期:[特殊字符] 深入理解MyBatis[特殊字符]MyBatis基础CRUD操作详解[特殊字符]

第二期:[特殊字符] 深入理解MyBatis[特殊字符]MyBatis基础CRUD操作详解[特殊字符]

2025/4/15 21:53:13 来源:https://blog.csdn.net/eternal__day/article/details/147173628  浏览:    关键词:第二期:[特殊字符] 深入理解MyBatis[特殊字符]MyBatis基础CRUD操作详解[特殊字符]

前言 🌟

在掌握了 MyBatis 的基本配置与环境搭建之后,接下来的重点便是深入理解其核心功能——CRUD 操作(增删改查)。💻

数据库操作是任何应用开发中不可或缺的一环,而 MyBatis 正是通过灵活的 SQL 映射机制,极大地简化了这些操作的实现过程。本篇将围绕最常见的数据库基本操作展开,带你从传统 JDBC 的冗杂代码,迈向 MyBatis 优雅高效的开发方式。

我们将通过实际案例,结合注解与 XML 两种方式,逐一讲解如何使用 MyBatis 实现:

  • 新增数据 🆕

  • 删除数据 ❌

  • 更新数据 🔁

  • 查询数据 🔍

同时,还将分析每种实现方式的优劣,帮助你根据项目需求做出合理的选择。

无论你是初学者,还是希望进一步深入理解 MyBatis 的开发者,都能从这篇内容中收获实用技巧与开发灵感。🚀


 基本操作回顾 🔁

MyBatis 的核心用途之一就是对数据库的 增删改查(CRUD) 操作进行简化和优化。在传统 JDBC 中,每次都需要写大量重复性的代码来完成这些操作,而在 MyBatis 中,你可以通过 注解XML 映射 两种方式优雅地完成同样的工作。

下面我们分别回顾这四种操作的基本语法,并通过两个方式(注解和 XML)进行展示。📘

1. 增、删、改、查的基本语法和实现方式 🔄

在数据库操作中,通常有四种基本操作:增(Insert)💾、删(Delete)🗑️、改(Update)🔧和查(Select)🔍。每种操作的基本语法如下:

  • 增(Insert) 🆕

    INSERT INTO table_name (column1, column2, column3, ...)
    VALUES (value1, value2, value3, ...);
    
  • 删(Delete)

    DELETE FROM table_name WHERE condition;
    
  • 改(Update) 🔄

    UPDATE table_name
    SET column1 = value1, column2 = value2, ...
    WHERE condition;
    
  • 查(Select) 👀

    SELECT column1, column2, column3, ...
    FROM table_name
    WHERE condition
    ORDER BY column1;
    

这些语法是进行数据库操作的基础,通常会结合特定的框架和技术来简化实现。🚀

2. SQL映射的定义(注解与XML方式) 📝

在 Java 中,使用 MyBatis 框架时,通常需要将 SQL 操作映射到 Java 方法。MyBatis 提供了两种方式来定义这些 SQL 映射:注解方式XML方式

注解方式 💡

在 MyBatis 中,你可以通过注解在接口方法上定义 SQL 语句。以下是常用的注解:

  • @Insert ✍️:用于插入数据。

  • @Update 🔄:用于更新数据。

  • @Delete 🗑️:用于删除数据。

  • @Select 🔍:用于查询数据。

示例:

public interface UserMapper {@Insert("INSERT INTO users (name, age) VALUES (#{name}, #{age})")void insertUser(User user);@Select("SELECT * FROM users WHERE id = #{id}")User selectUserById(int id);@Update("UPDATE users SET name = #{name}, age = #{age} WHERE id = #{id}")void updateUser(User user);@Delete("DELETE FROM users WHERE id = #{id}")void deleteUser(int id);
}
XML方式 📝

在 XML 映射文件中,SQL 语句被定义在 <mapper> 标签中。每个 SQL 操作通过不同的标签(如 <insert>, <select>, <update>, <delete>)进行映射。

示例:

UserMapper.xml

<mapper namespace="com.example.UserMapper"><insert id="insertUser" parameterType="User">INSERT INTO users (name, age)VALUES (#{name}, #{age})</insert><select id="selectUserById" resultType="User">SELECT * FROM users WHERE id = #{id}</select><update id="updateUser" parameterType="User">UPDATE usersSET name = #{name}, age = #{age}WHERE id = #{id}</update><delete id="deleteUser" parameterType="int">DELETE FROM users WHERE id = #{id}</delete>
</mapper>
🧩 注解 vs XML 映射方式对比
方式优点 🌟缺点 ⚠️适用场景 📌
注解方式简洁直观,代码集中在一处不适合复杂 SQL 语句简单的增删改查
XML方式结构清晰,适合复杂 SQL & 动态 SQL映射文件和接口分离,维护略复杂SQL 语句复杂、需灵活配置时
选择注解还是 XML? 🤔
  • 注解方式 ✅:简洁,适合小型项目或简单的 SQL 操作。

  • XML方式 📂:更灵活,适合复杂查询,且可以分离 SQL 和 Java 代码,提高可维护性。

一般来说,如果项目较小,且 SQL 操作较为简单,可以使用注解;而如果 SQL 语句复杂,或者希望保持 Java 代码与 SQL 的分离,XML 方式更加合适。🔧

在 MyBatis 中,插入操作(Insert)可以通过注解或 XML 配置两种方式实现。此外,利用 @Options 注解或 XML 配置中的 useGeneratedKeys 属性,可以实现插入数据后返回自增主键的功能。以下是对这两种方式的详细介绍和示例代码。


🆕 增操作(Insert)

在 MyBatis 中,执行插入操作主要有两种方式:使用 @Insert 注解 和 使用 XML 映射中的 <insert> 标签。两者都可以完成插入任务,但在处理返回主键时,写法稍有不同。

@Insert 注解与 XML 中 <insert> 标签的差异

1. 使用 @Insert 注解

@Insert 注解用于在 Mapper 接口中直接编写 SQL 语句,适用于简单的插入操作。例如:

@Insert("INSERT INTO users(name, age) VALUES(#{name}, #{age})")
int addUser(User user);

这种方式简洁明了,便于快速开发。然而,当 SQL 语句较为复杂或需要动态构建时,注解方式的可读性和维护性会降低。

2. 使用 XML 中的 <insert> 标签

在 XML 配置中,使用 <insert> 标签定义插入操作,适用于复杂的 SQL 语句和动态 SQL 的构建。例如:

<insert id="addUser" parameterType="User">INSERT INTO users(name, age)VALUES(#{name}, #{age})
</insert>

XML 配置方式提供了更高的灵活性和可维护性,特别是在处理复杂逻辑和动态 SQL 时更为合适。


利用 Options 配置返回自增主键

在插入数据后获取数据库生成的自增主键,可以通过以下两种方式实现:

1. 注解方式

在使用 @Insert 注解的同时,结合 @Options 注解配置返回主键的相关属性。例如:

@Insert("INSERT INTO users(name, age) VALUES(#{name}, #{age})")
@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")
int addUser(User user);

  • useGeneratedKeys = true:表示使用数据库自动生成的主键。

  • keyProperty = "id":指定将生成的主键值赋给 User 对象的 id 属性。

  • keyColumn = "id":指定数据库表中的主键列名。

这样配置后,插入操作执行完毕后,User 对象的 id 属性将自动填充为数据库生成的主键值。

2. XML 配置方式

在 XML 中的 <insert> 标签中设置相关属性,实现相同的功能。例如:

<insert id="addUser" parameterType="User" useGeneratedKeys="true" keyProperty="id" keyColumn="id">INSERT INTO users(name, age)VALUES(#{name}, #{age})
</insert>

配置说明与注解方式相同,执行插入操作后,User 对象的 id 属性将被自动赋值为生成的主键。


示例代码

以下是一个完整的示例,展示如何使用注解方式插入数据并返回自增主键:

public interface UserMapper {@Insert("INSERT INTO users(name, age) VALUES(#{name}, #{age})")@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")int addUser(User user);
}

在调用 addUser 方法后,User 对象的 id 属性将被自动填充为数据库生成的主键值。

如果使用 XML 配置方式,Mapper 接口方法可以简化为:

int addUser(User user);

对应的 XML 配置如下:

<insert id="addUser" parameterType="User" useGeneratedKeys="true" keyProperty="id" keyColumn="id">INSERT INTO users(name, age)VALUES(#{name}, #{age})
</insert>

这样配置后,同样可以在插入数据后自动获取并设置主键值。


❌ 删操作(Delete) & 🔁 改操作(Update)

在 MyBatis 中,删除(Delete)和更新(Update)操作可以通过注解或 XML 配置两种方式实现。在使用这些操作时,参数传递和绑定是关键,尤其是在方法参数较多或参数名与 SQL 中不一致时,合理使用 @Param 注解至关重要,除了掌握基本语法外,参数传递与绑定方式 是非常关键的一环,尤其是当方法中传入多个参数或参数名与 SQL 占位符不一致时,可能导致绑定失败或运行报错。

一.🧠 参数传递注意点

  1. 单个参数

    • 当方法只接受一个参数时,MyBatis 可以自动识别参数名,无需使用 @Param 注解。

    • 例如:

      @Delete("DELETE FROM users WHERE id = #{id}")
      int deleteUserById(int id);
      
  2. 多个参数

    • 当方法接受多个参数时,MyBatis 默认将参数命名为 param1param2 等,可能导致 SQL 中的参数名与方法参数不一致。

    • 为避免这种情况,建议使用 @Param 注解为每个参数指定名称。

    • 例如:

      @Update("UPDATE users SET name = #{name} WHERE id = #{id}")
      int updateUser(@Param("id") int id, @Param("name") String name);
      
  3. 使用 JavaBean 作为参数

    • 如果方法参数是一个 JavaBean 对象,MyBatis 会根据对象的属性名进行参数绑定,无需使用 @Param 注解。

    • 例如:

      @Update("UPDATE users SET name = #{name}, age = #{age} WHERE id = #{id}")
      int updateUser(User user);
      
  4. 使用 Map 作为参数

    • 当方法参数为 Map 类型时,SQL 中的参数名应与 Map 的键一致。

    • 例如:

      @Delete("DELETE FROM users WHERE id = #{userId}")
      int deleteUser(Map<String, Object> params);
      

二、注解方式实现删除和更新操作

1. 删除操作

  • 单个参数

  @Delete("DELETE FROM users WHERE id = #{id}")int deleteUserById(int id);

  • 多个参数(使用 @Param)

  @Delete("DELETE FROM users WHERE id = #{id} AND status = #{status}")int deleteUser(@Param("id") int id, @Param("status") String status);

2. 更新操作

  • 使用 JavaBean 作为参数

  @Update("UPDATE users SET name = #{name}, age = #{age} WHERE id = #{id}")int updateUser(User user);

  • 多个参数(使用 @Param)

  @Update("UPDATE users SET name = #{name} WHERE id = #{id}")int updateUser(@Param("id") int id, @Param("name") String name);


三、XML 方式实现删除和更新操作

1. 删除操作

<delete id="deleteUserById" parameterType="int">DELETE FROM users WHERE id = #{id}
</delete>

2. 更新操作

  • 使用 JavaBean 作为参数

  <update id="updateUser" parameterType="User">UPDATE usersSET name = #{name}, age = #{age}WHERE id = #{id}</update>

  • 多个参数(使用 @Param)

  <update id="updateUser" parameterType="map">UPDATE usersSET name = #{name}WHERE id = #{id}</update>


四、使用 @Param 注解的最佳实践

  • 多个参数时使用 @Param:当方法有多个参数时,使用 @Param 注解为每个参数指定名称,以确保 SQL 中的参数名与方法参数一致。

  • 避免使用 ${}:在 SQL 中使用 ${} 会直接拼接字符串,可能导致 SQL 注入风险。建议使用 #{} 进行参数绑定。

  • 参数名与 SQL 中一致:确保方法参数名与 SQL 中的参数名一致,或通过 @Param 注解进行明确绑定。


🔍 查询操作(Select)

在 MyBatis 中,查询是使用最频繁、最关键的操作之一。无论是查询单条记录还是查询列表,MyBatis 提供了丰富的方式来处理返回单个对象和列表的场景,同时也支持自动映射(result mapping)的机制,以便把数据库查询结果转换为 Java 对象。

但自动映射不是“万能”的,字段名不一致时容易出现问题,本节将详解如何解决这些常见坑点 👇


一、查询单个对象与列表的差异

  • 单个对象查询
    通常使用方法返回类型为对象(如 User)的查询接口。当查询结果只返回一行数据时,这样能直接将返回值自动映射到对应的 Java 对象。例如:

    @Select("SELECT id, name, age FROM users WHERE id = #{id}")
    User getUserById(int id);
    

    如果查询结果为空或多条记录,则可能会导致异常,此时需要保证查询条件唯一。

  • 列表查询
    当查询的结果可能包含多行数据时,接口返回值一般为 List<User>。MyBatis 会遍历每一行数据并调用映射规则将每行数据封装成一个 Java 对象,最终返回一个列表。例如:

    @Select("SELECT id, name, age FROM users")
    List<User> getAllUsers();
    

二、自动映射原理与字段映射问题

MyBatis 能自动将数据库查询的结果映射到 Java 对象中,但前提是 SQL 返回的列名和 Java 对象的属性名需要保持一致。实际应用中常遇到如下问题及相应解决方法:

1. 起别名(Alias)

如果数据库表中的列名与 Java 对象的属性名不一致,可以在 SQL 中使用别名。例如:

@Select("SELECT id, name AS userName, age FROM users WHERE id = #{id}")
User getUserById(int id);

这样 MyBatis 就能将查询结果中的 userName 列映射到 Java 对象中的 userName 属性上。

2. 结果映射(Result Map)

对于更复杂的情况,可以在 XML 中通过 <resultMap> 标签来定义映射关系。这样不仅灵活,而且可在一个地方统一管理映射规则。例如:

<resultMap id="userResultMap" type="com.example.User"><id column="id" property="id"/><result column="name" property="userName"/><result column="age" property="age"/>
</resultMap><select id="getUserById" resultMap="userResultMap" parameterType="int">SELECT id, name, age FROM users WHERE id = #{id}
</select>

此方式适用于字段较多、数据结构较复杂或者需要复用映射规则的场景。

3. 开启驼峰命名(Camel Case Mapping)

MyBatis 还支持通过全局配置来自动将下划线命名转换为驼峰命名,这样数据库列 user_name 会自动映射到 Java 属性 userName。可以在配置文件中启用该功能:

<settings><setting name="mapUnderscoreToCamelCase" value="true"/><!-- 也可以设置日志输出,见下节 --><setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

或者在 application.yml 中(使用 MyBatis-Spring Boot Starter 时)这样配置:

mybatis:configuration:map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImpl

这种方式使得数据库列名与 Java 属性之间的差异无需在每个 SQL 中显式别名,从而减少了维护成本。


三、配置日志打印 SQL、参数及执行结果

为了帮助调试,MyBatis 允许开发者配置日志输出,打印 SQL 语句、参数绑定以及执行结果。主要方法有:

1. 配置 MyBatis 日志实现

MyBatis 支持多种日志实现(例如:STDOUT_LOGGING、LOG4J、SLF4J 等)。可以在 MyBatis 配置文件中设置日志实现:

<settings><setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>

此配置会将所有 SQL 执行、参数绑定以及执行结果输出到控制台。

2. 配置日志框架

如果项目中使用 Log4j2 或 SLF4J 等日志框架,则需要在日志配置文件中启用 MyBatis 相关的日志记录器。例如,在 Log4j2 的配置文件中:

<Logger name="org.apache.ibatis" level="DEBUG" additivity="false"><AppenderRef ref="Console"/>
</Logger>

这样便能确保 MyBatis 执行过程中的详细日志输出到控制台,便于调试和性能分析。

3. 配置 application.yml 打印日志

logging:level:com.yourpackage.mapper: debug
mybatis:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

4. 运行时调试效果

调试过程中,会看到类似下面的日志输出:

DEBUG - ==>  Preparing: SELECT id, name, age FROM users WHERE id = ? 
DEBUG - ==> Parameters: 1(Integer)
DEBUG - <==      Total: 1

这显示了待执行的 SQL 语句、参数绑定情况以及执行结果的行数,极大地帮助开发者定位问题。


示例代码总结

注解方式示例(带驼峰配置)

@Mapper
public interface UserMapper {@Select("SELECT id, name AS userName, age FROM users WHERE id = #{id}")User getUserById(int id);@Select("SELECT id, name AS userName, age FROM users")List<User> getAllUsers();
}

XML 配置示例(使用 resultMap)

<resultMap id="userResultMap" type="com.example.User"><id column="id" property="id"/><result column="name" property="userName"/><result column="age" property="age"/>
</resultMap><select id="getUserById" resultMap="userResultMap" parameterType="int">SELECT id, name, age FROM users WHERE id = #{id}
</select><select id="getAllUsers" resultMap="userResultMap">SELECT id, name, age FROM users
</select>

全局配置开启驼峰命名与日志输出(例如,在 mybatis-config.xml 中)

<settings><setting name="mapUnderscoreToCamelCase" value="true"/><setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>


案例说明(JDBC和Mybaits操作数据库案例对比)

假设有一个简单的 User 表,结构如下(MySQL 语法示例):

CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50) NOT NULL,password VARCHAR(255) NOT NULL,email VARCHAR(100),created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

对应的 Java 实体类 User 如下:

public class User {private Integer id;private String username;private String password;private String email;private Timestamp createdAt;// Getters and Setters
}

Part 1:基于 JDBC 实现 CRUD

1.1 JDBC 工具类

创建一个简单的 JDBC 工具类,用于获取数据库连接并释放资源。

import java.sql.*;public class JDBCUtil {private static final String URL = "jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTC";private static final String USERNAME = "root";private static final String PASSWORD = "root123";static {try {Class.forName("com.mysql.cj.jdbc.Driver");} catch (ClassNotFoundException e) {e.printStackTrace();}}public static Connection getConnection() throws SQLException {return DriverManager.getConnection(URL, USERNAME, PASSWORD);}public static void close(Connection conn, Statement stmt, ResultSet rs) {try { if(rs != null) rs.close(); } catch (Exception e) { e.printStackTrace(); }try { if(stmt != null) stmt.close(); } catch (Exception e) { e.printStackTrace(); }try { if(conn != null) conn.close(); } catch (Exception e) { e.printStackTrace(); }}
}

1.2 JDBC 实现 CRUD 的 DAO

import java.sql.*;
import java.util.ArrayList;
import java.util.List;public class UserJDBCDao {// 增public int insertUser(User user) {String sql = "INSERT INTO users(username, password, email) VALUES (?, ?, ?)";Connection conn = null;PreparedStatement pstmt = null;try {conn = JDBCUtil.getConnection();pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);pstmt.setString(1, user.getUsername());pstmt.setString(2, user.getPassword());pstmt.setString(3, user.getEmail());int rows = pstmt.executeUpdate();// 获取自增主键ResultSet rs = pstmt.getGeneratedKeys();if (rs.next()) {user.setId(rs.getInt(1));}rs.close();return rows;} catch (SQLException e) {e.printStackTrace();return 0;} finally {JDBCUtil.close(conn, pstmt, null);}}// 删public int deleteUserById(int id) {String sql = "DELETE FROM users WHERE id = ?";Connection conn = null;PreparedStatement pstmt = null;try {conn = JDBCUtil.getConnection();pstmt = conn.prepareStatement(sql);pstmt.setInt(1, id);return pstmt.executeUpdate();} catch (SQLException e) {e.printStackTrace();return 0;} finally {JDBCUtil.close(conn, pstmt, null);}}// 改public int updateUserEmail(int id, String newEmail) {String sql = "UPDATE users SET email = ? WHERE id = ?";Connection conn = null;PreparedStatement pstmt = null;try {conn = JDBCUtil.getConnection();pstmt = conn.prepareStatement(sql);pstmt.setString(1, newEmail);pstmt.setInt(2, id);return pstmt.executeUpdate();} catch (SQLException e) {e.printStackTrace();return 0;} finally {JDBCUtil.close(conn, pstmt, null);}}// 查 —— 查询单个public User getUserById(int id) {String sql = "SELECT * FROM users WHERE id = ?";Connection conn = null;PreparedStatement pstmt = null;ResultSet rs = null;try {conn = JDBCUtil.getConnection();pstmt = conn.prepareStatement(sql);pstmt.setInt(1, id);rs = pstmt.executeQuery();if (rs.next()) {User user = new User();user.setId(rs.getInt("id"));user.setUsername(rs.getString("username"));user.setPassword(rs.getString("password"));user.setEmail(rs.getString("email"));user.setCreatedAt(rs.getTimestamp("created_at"));return user;}} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtil.close(conn, pstmt, rs);}return null;}// 查 —— 查询列表public List<User> getAllUsers() {String sql = "SELECT * FROM users";Connection conn = null;PreparedStatement pstmt = null;ResultSet rs = null;List<User> list = new ArrayList<>();try {conn = JDBCUtil.getConnection();pstmt = conn.prepareStatement(sql);rs = pstmt.executeQuery();while (rs.next()) {User user = new User();user.setId(rs.getInt("id"));user.setUsername(rs.getString("username"));user.setPassword(rs.getString("password"));user.setEmail(rs.getString("email"));user.setCreatedAt(rs.getTimestamp("created_at"));list.add(user);}} catch (SQLException e) {e.printStackTrace();} finally {JDBCUtil.close(conn, pstmt, rs);}return list;}
}

1.3 JDBC 测试代码示例

public class TestJDBC {public static void main(String[] args) {UserJDBCDao dao = new UserJDBCDao();// 插入数据User newUser = new User();newUser.setUsername("Bob");newUser.setPassword("pass123");newUser.setEmail("bob@example.com");int insertRows = dao.insertUser(newUser);System.out.println("JDBC 插入行数:" + insertRows + ", 生成的ID:" + newUser.getId());// 更新数据int updateRows = dao.updateUserEmail(newUser.getId(), "bob_new@example.com");System.out.println("JDBC 更新行数:" + updateRows);// 查询数据User queryUser = dao.getUserById(newUser.getId());System.out.println("JDBC 查询到的用户:" + queryUser.getUsername() + ", Email:" + queryUser.getEmail());// 删除数据int deleteRows = dao.deleteUserById(newUser.getId());System.out.println("JDBC 删除行数:" + deleteRows);}
}

JDBC 实现的优缺点

  • 优点:

    • 灵活度高,对连接、事务、异常处理有完全控制

  • 缺点:

    • 大量重复代码(获取连接、释放资源、异常处理)

    • 代码冗长,可读性和维护性较差


Part 2:基于 MyBatis 重构 CRUD

2.1 MyBatis 配置

配置文件(例如 application.yml 部分):

spring:datasource:url: jdbc:mysql://localhost:3306/testdb?useSSL=false&serverTimezone=UTCusername: rootpassword: root123driver-class-name: com.mysql.cj.jdbc.Drivermybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.example.demo.modelconfiguration:map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImpl

2.2 MyBatis Mapper 接口与映射文件

Mapper 接口(UserMapper.java)
package com.example.demo.mapper;import com.example.demo.model.User;
import org.apache.ibatis.annotations.*;import java.util.List;public interface UserMapper {@Insert("INSERT INTO users(username, password, email) VALUES (#{username}, #{password}, #{email})")@Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id")int insertUser(User user);@Delete("DELETE FROM users WHERE id = #{id}")int deleteUserById(@Param("id") int id);@Update("UPDATE users SET email = #{email} WHERE id = #{id}")int updateUserEmail(@Param("id") int id, @Param("email") String email);@Select("SELECT * FROM users WHERE id = #{id}")User getUserById(@Param("id") int id);@Select("SELECT * FROM users")List<User> getAllUsers();
}
对应 XML 映射文件(可选,下面以注解方式为主,略)

如果需要使用 XML 映射,可以将 SQL 语句放在 resources/mapper/UserMapper.xml 中,并在接口中不采用注解。

2.3 MyBatis 测试代码示例

使用 Spring Boot 进行单元测试:

import com.example.demo.mapper.UserMapper;
import com.example.demo.model.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;@SpringBootTest
public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testInsertUser() {User user = new User();user.setUsername("Alice");user.setPassword("alicepass");user.setEmail("alice@example.com");int rows = userMapper.insertUser(user);System.out.println("MyBatis 插入行数:" + rows);System.out.println("生成的主键 ID:" + user.getId());}@Testpublic void testUpdateUserEmail() {int rows = userMapper.updateUserEmail(1, "alice_new@example.com");System.out.println("MyBatis 更新行数:" + rows);}@Testpublic void testGetUserById() {User user = userMapper.getUserById(1);System.out.println("MyBatis 查询到的用户:" + user.getUsername() + ", Email:" + user.getEmail());}@Testpublic void testDeleteUser() {int rows = userMapper.deleteUserById(1);System.out.println("MyBatis 删除行数:" + rows);}@Testpublic void testGetAllUsers() {List<User> users = userMapper.getAllUsers();users.forEach(user -> System.out.println("用户:" + user.getUsername() + ", Email:" + user.getEmail()));}
}

MyBatis 实现的优缺点

  • 优点:

    • 极大减少重复代码,无需手动管理连接和资源

    • 通过注解或 XML 映射,SQL 与 Java 代码分离,维护性更高

    • 内置功能强大,例如动态 SQL、自动映射、日志输出等

  • 缺点:

    • 初期配置及学习曲线略高

    • 对于非常简单的场景,可能显得“杀鸡用牛刀”


Part 3:实际测试结果对比(IDEA 运行日志截图模拟)

JDBC 版运行日志(示例输出):

JDBC 插入行数:1, 生成的ID:10
JDBC 更新行数:1
JDBC 查询到的用户:Bob, Email:bob_new@example.com
JDBC 删除行数:1

说明:运行过程中,各步骤都需要手动捕获异常及关闭连接,在 IDEA 控制台可见大量重复日志信息。


MyBatis 版运行日志(示例输出):

==>  Preparing: INSERT INTO users(username, password, email) VALUES (?,?,?)
==>  Parameters: Alice(String), alicepass(String), alice@example.com(String)
<==    Updates: 1
MyBatis 插入行数:1
生成的主键 ID:12==>  Preparing: UPDATE users SET email = ? WHERE id = ?
==>  Parameters: alice_new@example.com(String), 1(Integer)
<==    Updates: 1
MyBatis 更新行数:1==>  Preparing: SELECT * FROM users WHERE id = ?
==>  Parameters: 1(Integer)
<==      Total: 1
MyBatis 查询到的用户:Alice, Email:alice_new@example.com==>  Preparing: DELETE FROM users WHERE id = ?
==>  Parameters: 1(Integer)
<==    Updates: 1
MyBatis 删除行数:1

说明:通过 MyBatis 的日志配置,可直接在控制台看到 SQL 语句、绑定参数及执行结果,大幅提升调试效率与可读性。


总结对比

  • 代码量:
    JDBC 实现需要大量重复代码(连接、语句、资源关闭等),而 MyBatis 通过映射注解和配置文件大大减少了冗余。

  • 易用性:
    使用 MyBatis 后,开发者可以专注于 SQL 和业务逻辑,无需关注细节的资源管理;同时日志配置方便调试。

  • 维护性:
    JDBC 代码中 SQL 嵌入 Java 中导致耦合度高,修改一处需要重新编译;而 MyBatis 通过 XML 或注解实现 SQL 与 Java 的分离,使得后期维护更加高效。

  • 调试:
    MyBatis 内置日志输出(显示具体 SQL、参数、执行结果),使问题排查变得简单直观,而 JDBC 的日志需要自行实现和维护。


结论

通过上面的案例演示,可以看到 MyBatis 在开发体验、代码维护与调试方面均优于传统的 JDBC 实现。在现代项目中,推荐优先考虑基于 MyBatis 或类似框架来进行数据持久化操作,从而提高整体开发效率与代码可维护性。


实际截图说明:
在 IDEA 中运行测试时,你可以截取各个测试方法的控制台日志。
例如:

  • JDBC 版的日志截图显示“JDBC 插入行数:1, 生成的ID:10”等信息。

  • MyBatis 版截图则包含了标准输出的 SQL 语句、参数及执行统计信息(类似上面的日志示例)。

由于本回答无法直接上传图片,你可以自行在 IDEA 中运行上述测试代码并截图保存以作参考。


希望这个完整的小案例能帮助你深刻理解传统 JDBC 与 MyBatis 在 CRUD 操作上的差异,并体会到 MyBatis 在简化代码和提高开发效率方面的优势!


结语 🎉

本文详细讲解了 MyBatis 基础 CRUD 操作的各个方面,从增删改查的基本语法到注解和 XML 映射方式的具体实现,再到参数绑定、自动映射和日志调试的使用技巧。通过这些示例与对比,我们可以发现:

  • 简化开发流程:MyBatis 通过灵活的 SQL 映射机制,大幅减少了传统 JDBC 开发中冗长且重复的代码。

  • 增强代码可维护性:SQL 语句与 Java 代码的分离使得代码结构更清晰,修改和扩展更加方便,解决了 SQL 与业务逻辑耦合的问题。

  • 方便调试与追踪:借助日志配置,开发者能够直观地查看 SQL 语句、参数绑定和执行结果,显著提高了调试效率。

  • 灵活应对复杂场景:无论是简单 CRUD 操作还是复杂的动态 SQL 构造,MyBatis 都能提供有效的支持,满足不同项目的需求。

总体来看,MyBatis 为开发者提供了一个高效、灵活和易维护的数据持久层解决方案,使得构建健壮和可扩展的企业级应用成为可能。希望本篇文章能帮助你更好地理解和掌握 MyBatis 的核心技术,并在实际项目中充分发挥其优势!🚀

继续深入探索 MyBatis 及其它持久化技术,你的开发技能必将更上一层楼!😊

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词