Spring Boot 集成 MyBatis 全面讲解

news2025/4/3 10:45:31

在这里插入图片描述

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、分页查询和复杂对象映射,为开发者提供了极大的灵活性。在项目中,结合实际场景选择合适的实现方式,可以显著提高开发效率并降低维护成本。如果有任何疑问,欢迎在评论区留言讨论!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2260249.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决Jmeter HTTP Cookie管理器cookie不生效

解决Jmeter HTTP Cookie管理器cookie不生效问题 解决Jmeter HTTP Cookie管理器cookie不生效问题1、设置Jmeter HTTP Cookie管理器cookie后&#xff0c;发起的请求显示[no cookies]jmeter问题复现&#xff1a;这里同样使用postman进行重试&#xff0c;发现是可以正常获取数据的&…

freeswitch(开启支持MCU视频会议,使用mod_av模块)

亲测版本centos 7.9系统–》 freeswitch1.10.9 本人freeswitch安装路径(根据自己的路径进入) /usr/local/freeswitch/etc/freeswitch场景说明: 有些场景想使用视频会议MCU融合画面进行开会使用方法: 第一步:下载插件 yum install -y epel-release yum install

IntelliJ IDEA 使用技巧与插件推荐

目录 常用使用技巧 1. 使用快捷键提升开发效率 2. 多光标编辑 3. 代码自动补全 4. 使用 Find Action 快速执行操作 5. 集成版本控制系统&#xff08;VCS&#xff09; 6. 快速查看代码文档 推荐插件 1. Lombok Plugin 2. Rainbow Brackets 3. Key Promoter X 4. Chec…

Centos7环境下安装Flink1.20

目录 介绍1、涉及安装包2、节点3、修改hostname4、将flink安装包上传并解压5、修改配置文件6、修改masters和workers&#xff08;所有节点&#xff09;7、集群启停 介绍 Flink 是一个分布式系统&#xff0c;需要有效分配和管理计算资源才能执行流应用程序。它集成了所有常见的…

CTFHub 技能树 Web RCE eval执行(学习记录)

eval执行 源代码 <?php if (isset($_REQUEST[cmd])) {eval($_REQUEST["cmd"]); } else {highlight_file(__FILE__); } ?> PHP代码显示&#xff0c;要求将命令赋值给cmd然后执行 先查看一下根目录文件 /?cmdsystem("ls"); 查看上一级目录找flag文…

人员离岗监测摄像机智能人员睡岗、逃岗监测 Python 语言结合 OpenCV

在安全生产领域&#xff0c;人员的在岗状态直接关系到生产流程的顺利进行和工作环境的安全稳定。人员离岗监测摄像机的出现&#xff0c;为智能人员睡岗、逃岗监测提供了高效精准的解决方案&#xff0c;而其中的核心技术如AI识别睡岗脱岗以及相关的算法盒子和常见的安全生产AI算…

Web day11 SpringBoot原理

目录 1.配置优先级&#xff1a; 2.Bean的管理&#xff1a; bean的作用域&#xff1a; 第三方bean&#xff1a; 方案一&#xff1a; 方案二&#xff1a; SpringBoot原理&#xff1a; 扫描第三方包&#xff1a; 方案1&#xff1a;ComponentScan 组件扫描 方案2&#xff1…

ECharts柱状图-柱图2,附视频讲解与代码下载

引言&#xff1a; 在数据可视化的世界里&#xff0c;ECharts凭借其丰富的图表类型和强大的配置能力&#xff0c;成为了众多开发者的首选。今天&#xff0c;我将带大家一起实现一个柱状图图表&#xff0c;通过该图表我们可以直观地展示和分析数据。此外&#xff0c;我还将提供…

VMware安装ubuntu22教程

文章目录 软件环境1、打开vmware&#xff0c;选择创建新的虚拟机2、选典型安装&#xff0c;然后点击下一步3、选择稍后安装操作系统&#xff0c;点击下一步4、版本选择Ubuntu 64位&#xff0c;点击下一步5、输入虚拟机名称和规划的安装盘符路径6、最大磁盘大小选择20G&#xff…

利用usb-cam包标定RealSense D435相机(未解决版)

一、 安装usb-cam包和标定数据包 usb_cam 包的主要作用是将 USB 摄像头的视频流转换为 ROS 可用的消息格式。 sudo apt-get install ros-melodic-usb-cam camera_calibration 包是 ROS 中用于相机标定的工具包&#xff0c;主要用于校准相机的内参和外参。 sudo apt-get ins…

Kafka系列教程 - Kafka 生产者 -2

1. 生产者简介 不管是把 Kafka 作为消息队列系统、还是数据存储平台&#xff0c;总是需要一个可以向 Kafka 写入数据的生产者和一个可以从 Kafka 读取数据的消费者&#xff0c;或者是一个兼具两种角色的应用程序。 使用 Kafka 的场景很多&#xff0c;诉求也各有不同&#xff…

基于卷积神经网络的图像二分类检测模型训练与推理实现教程 | 幽络源

前言 对于本教程&#xff0c;说白了&#xff0c;就是期望能通过一个程序判断一张图片是否为某个物体&#xff0c;或者说判断一张图片是否为某个缺陷。因为本教程是针对二分类问题&#xff0c;因此主要处理 是 与 不是 的问题&#xff0c;比如我的模型是判断一张图片是否为苹果…

SpringBoot集成JWT和Redis实现鉴权登录功能

目前市面上有许多鉴权框架&#xff0c;鉴权原理大同小异&#xff0c;本文简单介绍下利用JWT和Redis实现鉴权功能&#xff0c;算是抛砖引玉吧。 主要原理就是“令牌主动失效机制”&#xff0c;主要包括以下4个步骤&#xff1a; (1)利用拦截器LoginInterceptor实现所有接口登录拦…

初识Robot Framework测试框架

Robot Framework 是一款用 Python 编写的通用型测试框架&#xff0c;具备良好的可扩展性&#xff0c;支持关键字驱动&#xff0c;可以同时测试多种类型的客户端&#xff08;Web、PC、移动端&#xff09;或者接口&#xff0c;也可以进行分布式测试执行。常用于验收测试和验收测试…

Windows安装elasticsearch、Kibana以及IK分词器

一、下载 1.下载elasticsearch 访问官网Download Elasticsearch | Elastic&#xff0c;下载elasticsearch 2.下载 Kibana 访问Download Kibana Free | Get Started Now | Elastic &#xff0c;下载 Kibana 3. IK分词器下载 访问Gitee 极速下载/elasticsearch-analysis-ik选…

socket编程UDP-实现停等机制(接收确认、超时重传)

在下面博客中&#xff0c;我介绍了利用UDP模拟TCP连接、按数据包发送文件的过程&#xff0c;并附上完整源码。 socket编程UDP-文件传输&模拟TCP建立连接脱离连接&#xff08;进阶篇&#xff09;_udp socket发送-CSDN博客 下面博客实现的是滑动窗口机制&#xff1a; sock…

PHP项目从 php5.3 版本升级到 php8.3 版本时的一些问题和解决方法记录

一个原来的项目&#xff0c;因为业务需要&#xff0c;进行了PHP版本升级&#xff0c;从php5.3直接升级到php8.3。变化挺大的&#xff0c;原程序中有很多不再兼容&#xff0c;在此处进行一下记录。 一、Deprecated: 显式转换问题 报错内容&#xff1a;Deprecated: Implicit con…

在Liunx中安装JDK、Tomcat、mysql、lrzsz、Nginx

一.软件安装方式 在Linux系统中&#xff0c;安装软件的方式主要有四种&#xff0c;这四种安装方式的特点如下&#xff1a; 二.安装JDK 上述我们介绍了Linux系统软件安装的四种形式&#xff0c;接下来我们就通过第一种(二进制发 布包)形式来安装JDK。 在/下创建soft目录&…

LeetCode-hot100-73

https://leetcode.cn/problems/largest-rectangle-in-histogram/description/?envTypestudy-plan-v2&envIdtop-100-liked 84. 柱状图中最大的矩形 已解答 困难 相关标签 相关企业 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#x…

leetcode-73.矩阵置零-day5

class Solution {public void setZeroes(int[][] mat) {int m mat.length, n mat[0].length;// 1. 扫描「首行」和「首列」记录「首行」和「首列」是否该被置零boolean r0 false, c0 false;for (int i 0; i < m; i) {if (mat[i][0] 0) {r0 true;break;}}for (int j …