Spring Boot 集成 MyBatis 全面讲解

Spring Boot 集成 MyBatis 全面讲解

MyBatis 是一款优秀的持久层框架,与 Spring Boot 集成后可以大大简化开发流程。本文将全面讲解如何在 Spring Boot 中集成 MyBatis,包括环境配置、基础操作、高级功能和最佳实践。


一、MyBatis 简介

1. SqlSession

SqlSession 是 MyBatis 的核心接口,负责执行 SQL 语句、获取映射器实例以及管理事务。

1.1 SqlSession 的创建

SqlSession 通常通过 SqlSessionFactory 获取。以下是创建 SqlSessionFactory 的典型代码:

复制代码
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (SqlSession session = sqlSessionFactory.openSession()) {
    // 使用 session 进行数据库操作
}

注意 :在 Spring 集成中,SqlSessionFactorySqlSession 的创建由框架管理,我们只需要通过依赖注入获取即可。


1.2 SqlSession 的常用方法

SqlSession 提供了多种方法,用于执行数据库操作:

  • 查询操作

    复制代码
    // 单条记录查询
    User user = session.selectOne("namespace.statementId", parameter);
    
    // 多条记录查询
    List<User> users = session.selectList("namespace.statementId", parameter);
  • 插入操作

    复制代码
    int rows = session.insert("namespace.statementId", parameter);
  • 更新操作

    复制代码
    int rows = session.update("namespace.statementId", parameter);
  • 删除操作

    复制代码
    int rows = session.delete("namespace.statementId", parameter);
  • 事务控制

    复制代码
    session.commit();  // 提交事务
    session.rollback();  // 回滚事务

2. Mapper 映射器

Mapper 映射器是 MyBatis 的核心功能,用于实现 SQL 和 Java 方法之间的映射。它可以通过注解或 XML 配置。

2.1 基于注解的 Mapper

注解方式直接将 SQL 写在 Mapper 接口中,简单高效,适合简单场景。

示例代码:

复制代码
@Mapper
public interface UserMapper {

    @Select("SELECT * FROM user WHERE id = #{id}")
    User selectById(Long id);

    @Insert("INSERT INTO user (username, email) VALUES (#{username}, #{email})")
    int insertUser(User user);

    @Update("UPDATE user SET email = #{email} WHERE id = #{id}")
    int updateUser(User user);

    @Delete("DELETE FROM user WHERE id = #{id}")
    int deleteUser(Long id);
}

2.2 基于 XML 的 Mapper

XML 配置更加灵活,适合复杂查询场景。Mapper XML 文件通常位于 resources/mapper 目录。

Mapper 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.mapper.UserMapper">

    <!-- 查询 -->
    <select id="selectById" parameterType="long" resultType="com.example.entity.User">
        SELECT * FROM user WHERE id = #{id}
    </select>

    <!-- 插入 -->
    <insert id="insertUser" parameterType="com.example.entity.User">
        INSERT INTO user (username, email)
        VALUES (#{username}, #{email})
    </insert>

    <!-- 更新 -->
    <update id="updateUser" parameterType="com.example.entity.User">
        UPDATE user SET email = #{email} WHERE id = #{id}
    </update>

    <!-- 删除 -->
    <delete id="deleteUser" parameterType="long">
        DELETE FROM user WHERE id = #{id}
    </delete>
</mapper>

2.3 Mapper 映射器的工作机制

Mapper 接口的方法名和参数需要与 XML 中的 idparameterType 对应。MyBatis 会通过动态代理为 Mapper 接口生成实现类,并调用对应的 SQL。


3. 配置文件

MyBatis 的配置文件包括全局配置文件(mybatis-config.xml)和映射文件(mapper.xml)。


3.1 全局配置文件

mybatis-config.xml 定义了数据库连接、日志设置、别名等全局配置。

典型配置示例

复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 环境配置 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 别名配置 -->
    <typeAliases>
        <typeAlias type="com.example.entity.User" alias="User"/>
    </typeAliases>

    <!-- Mapper 映射文件 -->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>

3.2 映射文件配置

映射文件定义了具体的 SQL 和 Java 对象之间的关系。以 UserMapper.xml 为例:

复制代码
<mapper namespace="com.example.mapper.UserMapper">

    <select id="selectAll" resultType="User">
        SELECT * FROM user
    </select>

    <resultMap id="UserResultMap" type="User">
        <id column="id" property="id"/>
        <result column="username" property="username"/>
        <result column="email" property="email"/>
    </resultMap>
</mapper>

4. ResultMap

ResultMap 是 MyBatis 的强大特性之一,用于处理复杂查询结果与 Java 对象的映射关系。


4.1 什么是 ResultMap?

ResultMap 用于自定义数据库字段与 Java 对象属性的映射。它支持嵌套映射、别名和字段处理,适合复杂的对象映射场景。


4.2 ResultMap 配置示例

以下是一个带嵌套对象的 ResultMap 配置:

数据库表:
复制代码
CREATE TABLE user (
    id BIGINT PRIMARY KEY,
    username VARCHAR(50),
    email VARCHAR(100)
);

CREATE TABLE address (
    id BIGINT PRIMARY KEY,
    user_id BIGINT,
    city VARCHAR(50),
    FOREIGN KEY (user_id) REFERENCES user(id)
);
Java 对象:
复制代码
@Data
public class User {
    private Long id;
    private String username;
    private String email;
    private Address address;
}

@Data
public class Address {
    private Long id;
    private String city;
}
ResultMap 配置:
复制代码
<resultMap id="UserWithAddress" type="User">
    <id column="id" property="id"/>
    <result column="username" property="username"/>
    <result column="email" property="email"/>
    <association property="address" javaType="Address">
        <id column="address_id" property="id"/>
        <result column="city" property="city"/>
    </association>
</resultMap>
查询语句:
复制代码
<select id="getUserWithAddress" resultMap="UserWithAddress">
    SELECT u.id, u.username, u.email, a.id AS address_id, a.city
    FROM user u
    LEFT JOIN address a ON u.id = a.user_id
    WHERE u.id = #{id}
</select>

4.3 嵌套集合映射

对于一对多的嵌套关系,可以使用 <collection>

复制代码
<resultMap id="UserWithPosts" type="User">
    <id column="id" property="id"/>
    <result column="username" property="username"/>
    <collection property="posts" ofType="Post">
        <id column="post_id" property="id"/>
        <result column="title" property="title"/>
    </collection>
</resultMap>

总结

SqlSessionMapper配置文件ResultMap 是 MyBatis 的核心概念。通过灵活的配置和映射,MyBatis 可以高效地处理各种复杂的数据库操作需求。熟练掌握这些特性可以让开发者在项目中更高效地处理数据访问逻辑。


三、Spring Boot 集成 MyBatis

MyBatis 是一种轻量级的持久层框架,与 Spring Boot 集成后可以极大地提升开发效率。以下是集成的完整步骤,包括项目配置、数据库设计和基本操作。


1. 创建 Spring Boot 项目

在创建项目时,可以使用 Spring Initializr 快速生成骨架项目。以下依赖是集成 MyBatis 所必需的:

  • Spring Web:用于创建 REST API。
  • MyBatis Framework:MyBatis 的核心依赖。
  • MySQL Driver:连接 MySQL 数据库。
  • Lombok:简化实体类的开发,减少样板代码。

2. 配置 pom.xml

以下是需要在 pom.xml 中添加的 Maven 依赖:

复制代码
<dependencies>
    <!-- Spring Boot Starter -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <!-- MyBatis Starter -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>3.0.0</version>
    </dependency>

    <!-- MySQL Driver -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
    </dependency>

    <!-- Lombok -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

这些依赖包括 Spring Boot 核心、MyBatis 框架、MySQL 数据库驱动和 Lombok。版本号可以根据项目需求进行调整。


3. 配置数据库连接

src/main/resources 目录下创建 application.yml 文件,用于配置项目的数据库连接。

application.yml 示例
复制代码
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=UTC
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.demo.entity

说明

  • url:数据库连接地址。
  • usernamepassword:数据库的用户名和密码。
  • mapper-locations:指定 MyBatis 的 XML 映射文件路径。
  • type-aliases-package:指定实体类所在的包,用于启用简化的类名映射。

4. 创建数据库表

使用以下 SQL 语句创建一个简单的用户表:

SQL 示例
复制代码
CREATE DATABASE IF NOT EXISTS mybatis_demo;

USE mybatis_demo;

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

此 SQL 创建了一个名为 user 的表,用于存储用户信息。字段包括用户 ID、用户名、密码、电子邮件以及创建时间。


5. 编写实体类

创建与数据库表对应的 Java 实体类。

User.java
复制代码
package com.example.demo.entity;

import lombok.Data;
import java.time.LocalDateTime;

@Data
public class User {
    private Long id;
    private String username;
    private String password;
    private String email;
    private LocalDateTime createdAt;
}

说明

  • 使用了 Lombok 的 @Data 注解,自动生成 gettersettertoString 等方法。
  • 字段名称与数据库表的列名保持一致,便于自动映射。

6. 创建 Mapper 接口

MyBatis 的 Mapper 接口用于定义数据库操作。可以选择使用注解方式或者 XML 配置方式编写 SQL。

注解方式 Mapper

以下是一个基于注解的 Mapper 接口示例:

复制代码
package com.example.demo.mapper;

import com.example.demo.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

@Mapper
public interface UserMapper {

    @Insert("INSERT INTO user (username, password, email) VALUES (#{username}, #{password}, #{email})")
    int insertUser(User user);

    @Select("SELECT * FROM user WHERE id = #{id}")
    User selectById(Long id);

    @Select("SELECT * FROM user")
    List<User> selectAllUsers();

    @Update("UPDATE user SET username = #{username}, password = #{password}, email = #{email} WHERE id = #{id}")
    int updateUser(User user);

    @Delete("DELETE FROM user WHERE id = #{id}")
    int deleteUser(Long id);
}

XML 配置方式 Mapper

XML 配置方式更灵活,适合复杂查询场景。以下是对应的 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.demo.mapper.UserMapper">

    <insert id="insertUser" parameterType="com.example.demo.entity.User">
        INSERT INTO user (username, password, email)
        VALUES (#{username}, #{password}, #{email})
    </insert>

    <select id="selectById" parameterType="long" resultType="com.example.demo.entity.User">
        SELECT * FROM user WHERE id = #{id}
    </select>

    <select id="selectAllUsers" resultType="com.example.demo.entity.User">
        SELECT * FROM user
    </select>

    <update id="updateUser" parameterType="com.example.demo.entity.User">
        UPDATE user SET username = #{username}, password = #{password}, email = #{email} WHERE id = #{id}
    </update>

    <delete id="deleteUser" parameterType="long">
        DELETE FROM user WHERE id = #{id}
    </delete>

</mapper>

在 Spring Boot 中,MyBatis 会自动扫描 mapper 文件夹下的 XML 文件。


7. 创建 Service 层

为了更好地分离业务逻辑,建议将 Mapper 操作封装到 Service 层中。

UserService.java
复制代码
package com.example.demo.service;

import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    private final UserMapper userMapper;

    public UserService(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    public int createUser(User user) {
        return userMapper.insertUser(user);
    }

    public User getUserById(Long id) {
        return userMapper.selectById(id);
    }

    public List<User> getAllUsers() {
        return userMapper.selectAllUsers();
    }

    public int updateUser(User user) {
        return userMapper.updateUser(user);
    }

    public int deleteUser(Long id) {
        return userMapper.deleteUser(id);
    }
}

8. 创建 Controller 层

最后,为了提供对外接口,创建 Controller。

UserController.java
复制代码
package com.example.demo.controller;

import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @PostMapping
    public String createUser(@RequestBody User user) {
        userService.createUser(user);
        return "User created successfully!";
    }

    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getUserById(id);
    }

    @GetMapping
    public List<User> getAllUsers() {
        return userService.getAllUsers();
    }

    @PutMapping
    public String updateUser(@RequestBody User user) {
        userService.updateUser(user);
        return "User updated successfully!";
    }

    @DeleteMapping("/{id}")
    public String deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return "User deleted successfully!";
    }
}

9. 启动应用

创建项目主类 MyBatisDemoApplication.java

复制代码
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyBatisDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyBatisDemoApplication.class, args);
    }
}

启动项目,使用工具(如 Postman 或 CURL)测试接口。


四、MyBatis 基础操作详解

以下将详细讲解 MyBatis 的基础操作,包括如何创建实体类、Mapper 接口、XML 映射文件,以及如何通过 Service 和 Controller 层完成基础的增删改查功能。


1. 创建实体类

实体类用于表示数据库中的表记录,在 MyBatis 中,实体类字段与数据库表的列进行一一对应。

示例代码:User.java
复制代码
package com.example.demo.entity;

import lombok.Data;
import java.time.LocalDateTime;

@Data
public class User {
    private Long id;             // 用户ID
    private String username;     // 用户名
    private String password;     // 密码
    private String email;        // 邮箱
    private LocalDateTime createdAt; // 创建时间
}

说明

  • 使用 @Data 注解自动生成 gettersettertoString 等方法。
  • 字段名称与数据库表的列名保持一致,便于 MyBatis 自动映射。

2. 创建 Mapper 接口

Mapper 接口定义了对数据库表的操作。MyBatis 支持两种方式:基于注解和基于 XML 映射文件。

基于注解的 Mapper 接口

以下是使用注解定义的基础增删改查操作:

复制代码
package com.example.demo.mapper;

import com.example.demo.entity.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

@Mapper
public interface UserMapper {

    // 插入用户
    @Insert("INSERT INTO user (username, password, email) VALUES (#{username}, #{password}, #{email})")
    int insertUser(User user);

    // 查询所有用户
    @Select("SELECT * FROM user")
    List<User> getAllUsers();

    // 根据 ID 查询用户
    @Select("SELECT * FROM user WHERE id = #{id}")
    User getUserById(Long id);

    // 更新用户
    @Update("UPDATE user SET username = #{username}, password = #{password}, email = #{email} WHERE id = #{id}")
    int updateUser(User user);

    // 删除用户
    @Delete("DELETE FROM user WHERE id = #{id}")
    int deleteUser(Long id);
}

注意

  • 使用 @Mapper 注解让 Spring 容器自动扫描 Mapper 接口。
  • 注解方式适合简单的 SQL 语句,对于复杂查询建议使用 XML。

3. 配置 XML 映射文件

在复杂查询场景中,XML 配置文件更加灵活。

文件位置
复制代码
src/main/resources/mapper/UserMapper.xml
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.demo.mapper.UserMapper">

    <!-- 定义字段与属性的映射 -->
    <resultMap id="UserResultMap" type="com.example.demo.entity.User">
        <id column="id" property="id" />
        <result column="username" property="username" />
        <result column="password" property="password" />
        <result column="email" property="email" />
        <result column="created_at" property="createdAt" />
    </resultMap>

    <!-- 查询所有用户 -->
    <select id="getAllUsers" resultMap="UserResultMap">
        SELECT * FROM user
    </select>

    <!-- 插入用户 -->
    <insert id="insertUser" parameterType="com.example.demo.entity.User">
        INSERT INTO user (username, password, email)
        VALUES (#{username}, #{password}, #{email})
    </insert>

    <!-- 更新用户 -->
    <update id="updateUser" parameterType="com.example.demo.entity.User">
        UPDATE user
        SET username = #{username}, password = #{password}, email = #{email}
        WHERE id = #{id}
    </update>

    <!-- 删除用户 -->
    <delete id="deleteUser" parameterType="long">
        DELETE FROM user WHERE id = #{id}
    </delete>

</mapper>

注意

  • namespace 必须与 Mapper 接口的全路径名称一致。
  • <resultMap> 定义了表字段与实体类属性之间的映射关系。
  • #{} 用于参数占位,MyBatis 会根据参数类型自动替换。

4. 创建 Service 层

为了实现业务逻辑与数据访问的分离,建议通过 Service 层封装 Mapper 的操作。

示例代码:UserService.java
复制代码
package com.example.demo.service;

import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    private final UserMapper userMapper;

    public UserService(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    // 添加用户
    public int addUser(User user) {
        return userMapper.insertUser(user);
    }

    // 获取所有用户
    public List<User> getAllUsers() {
        return userMapper.getAllUsers();
    }

    // 根据 ID 查询用户
    public User getUserById(Long id) {
        return userMapper.getUserById(id);
    }

    // 更新用户
    public int updateUser(User user) {
        return userMapper.updateUser(user);
    }

    // 删除用户
    public int deleteUser(Long id) {
        return userMapper.deleteUser(id);
    }
}

说明

  • 通过依赖注入的方式引入 UserMapper
  • 将所有的数据库操作封装为独立的方法,便于管理和复用。

5. 创建 Controller 层

Controller 层提供 RESTful API 接口,供外部访问 Service 方法。

示例代码:UserController.java
复制代码
package com.example.demo.controller;

import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/users")
public class UserController {

    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    // 创建用户
    @PostMapping
    public String createUser(@RequestBody User user) {
        userService.addUser(user);
        return "User created successfully!";
    }

    // 获取所有用户
    @GetMapping
    public List<User> getAllUsers() {
        return userService.getAllUsers();
    }

    // 根据 ID 获取用户
    @GetMapping("/{id}")
    public User getUserById(@PathVariable Long id) {
        return userService.getUserById(id);
    }

    // 更新用户
    @PutMapping
    public String updateUser(@RequestBody User user) {
        userService.updateUser(user);
        return "User updated successfully!";
    }

    // 删除用户
    @DeleteMapping("/{id}")
    public String deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return "User deleted successfully!";
    }
}

说明

  • 使用 @RestController 标注类,返回 JSON 数据。
  • 通过 @RequestBody 接收前端传递的 JSON 数据。
  • 通过 @PathVariable 获取 URL 中的动态参数。

五、高级功能

1. 动态 SQL

动态 SQL 是 MyBatis 的强大功能之一,可以根据输入条件动态生成 SQL 语句。相比手动拼接 SQL,这种方式更加安全、高效且可维护。

1.1 动态 SQL 标签

MyBatis 提供了以下动态 SQL 标签:

  1. <if>:用于条件判断。
  2. <choose> :类似于 Java 的 switch-case
  3. <where> :自动添加 WHERE 关键字并处理多个条件。
  4. <set> :动态生成 SET 子句,常用于更新语句。
  5. <foreach> :用于迭代生成 SQL(如 IN 子句或批量插入)。
  6. <trim>:自定义 SQL 前后缀(如添加括号、处理多余逗号等)。

1.2 动态 SQL 示例

(1)条件查询:根据用户输入动态生成查询条件

XML 配置文件:

复制代码
<select id="searchUsers" resultMap="UserResultMap">
    SELECT * FROM user
    <where>
        <if test="username != null">
            AND username = #{username}
        </if>
        <if test="email != null">
            AND email = #{email}
        </if>
    </where>
</select>

注意<where> 标签会自动处理条件的拼接,并在至少有一个条件成立时自动添加 WHERE 关键字。

Java 调用代码:

复制代码
Map<String, Object> params = new HashMap<>();
params.put("username", "John");
params.put("email", null);

List<User> users = userMapper.searchUsers(params);

(2)动态更新:根据非空字段更新用户信息

在实际场景中,往往需要对部分字段进行更新,MyBatis 的动态 SQL 可以轻松实现。

XML 配置文件:

复制代码
<update id="updateUser" parameterType="User">
    UPDATE user
    <set>
        <if test="username != null">
            username = #{username},
        </if>
        <if test="password != null">
            password = #{password},
        </if>
        <if test="email != null">
            email = #{email},
        </if>
    </set>
    WHERE id = #{id}
</update>

注意

  • <set> 标签会自动处理逗号,确保生成的 SQL 语句语法正确。
  • null 值的字段会被忽略,避免误更新。

Java 调用代码:

复制代码
User user = new User();
user.setId(1L);
user.setUsername("NewName");

int rows = userMapper.updateUser(user);

(3)批量查询:使用 <foreach> 生成 IN 子句

XML 配置文件:

复制代码
<select id="findUsersByIds" resultMap="UserResultMap">
    SELECT * FROM user
    WHERE id IN
    <foreach collection="idList" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>

说明

  • collection 指定输入参数(一般为 List 或数组)。
  • item 是每次迭代的变量。
  • openseparatorclose 分别定义 SQL 子句的开头、分隔符和结尾。

Java 调用代码:

复制代码
List<Long> idList = Arrays.asList(1L, 2L, 3L);
List<User> users = userMapper.findUsersByIds(idList);

生成的 SQL:

复制代码
SELECT * FROM user WHERE id IN (1, 2, 3);

2. 分页查询

分页查询是 Web 应用中最常见的功能之一。在 MyBatis 中,可以借助 PageHelper 插件实现高效分页。


2.1 使用 PageHelper 插件

(1)引入依赖

pom.xml 中添加以下依赖:

复制代码
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.0</version>
</dependency>

(2)分页查询示例

在 Service 层调用分页方法:

复制代码
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

public List<User> getUsersByPage(int pageNum, int pageSize) {
    // 启用分页
    PageHelper.startPage(pageNum, pageSize);
    List<User> users = userMapper.getAllUsers();
    // 封装分页结果
    return new PageInfo<>(users).getList();
}

(3)自定义分页

如果不想引入插件,也可以通过手动拼接分页 SQL:

XML 配置文件:

复制代码
<select id="getUsersByPage" resultMap="UserResultMap">
    SELECT * FROM user
    LIMIT #{offset}, #{pageSize}
</select>

Mapper 接口:

复制代码
List<User> getUsersByPage(@Param("offset") int offset, @Param("pageSize") int pageSize);

Java 调用代码:

复制代码
int offset = (pageNum - 1) * pageSize;
List<User> users = userMapper.getUsersByPage(offset, pageSize);

3. 复杂对象映射
3.1 一对多映射

场景:一个用户有多个订单。

数据库表设计:

复制代码
CREATE TABLE orders (
    id BIGINT PRIMARY KEY,
    user_id BIGINT,
    order_name VARCHAR(255),
    FOREIGN KEY (user_id) REFERENCES user(id)
);

XML 配置文件:

复制代码
<resultMap id="UserWithOrders" type="User">
    <id column="id" property="id"/>
    <result column="username" property="username"/>
    <collection property="orders" ofType="Order">
        <id column="order_id" property="id"/>
        <result column="order_name" property="orderName"/>
    </collection>
</resultMap>

<select id="getUserWithOrders" resultMap="UserWithOrders">
    SELECT u.id, u.username, o.id AS order_id, o.order_name
    FROM user u
    LEFT JOIN orders o ON u.id = o.user_id
    WHERE u.id = #{id}
</select>

3.2 嵌套查询

对于复杂的多表查询,可以使用嵌套查询实现。

XML 配置:

复制代码
<resultMap id="OrderResultMap" type="Order">
    <id column="id" property="id"/>
    <result column="order_name" property="orderName"/>
</resultMap>

<resultMap id="UserWithOrders" type="User">
    <id column="id" property="id"/>
    <result column="username" property="username"/>
    <collection property="orders" resultMap="OrderResultMap" column="id"/>
</resultMap>

<select id="getUserWithOrders" resultMap="UserWithOrders">
    SELECT * FROM user WHERE id = #{id};
</select>

六、最佳实践
1. 分层设计
  • Controller 层:负责接收请求和返回响应。
  • Service 层:封装业务逻辑。
  • Mapper 层:专注于数据库交互。
2. 避免 N+1 查询

一对多、多对多场景中,优先使用联合查询或嵌套查询,避免多个 SQL 执行。

3. 启用日志

application.yml 中启用 MyBatis 日志:

复制代码
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
4. 动态 SQL
  • 使用 <foreach> 实现批量操作。
  • 使用 <if> 结合 <set> 实现动态更新。

总结

MyBatis 的高级功能如动态 SQL、分页查询和复杂对象映射,为开发者提供了极大的灵活性。在项目中,结合实际场景选择合适的实现方式,可以显著提高开发效率并降低维护成本。如果有任何疑问,欢迎在评论区留言讨论!

相关推荐
bobz9652 分钟前
ovs patch port 对比 veth pair
后端
Asthenia041212 分钟前
Java受检异常与非受检异常分析
后端
uhakadotcom26 分钟前
快速开始使用 n8n
后端·面试·github
JavaGuide33 分钟前
公司来的新人用字符串存储日期,被组长怒怼了...
后端·mysql
bobz96543 分钟前
qemu 网络使用基础
后端
Asthenia04121 小时前
面试攻略:如何应对 Spring 启动流程的层层追问
后端
Asthenia04121 小时前
Spring 启动流程:比喻表达
后端
Asthenia04122 小时前
Spring 启动流程分析-含时序图
后端
ONE_Gua2 小时前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·后端·爬虫
致心2 小时前
记一次debian安装mariadb(带有迁移数据)
后端