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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Web 毕设篇-适合小白、初级入门练手的 Spring Boot Web 毕业设计项目:电影院后台管理系统(前后端源码 + 数据库 sql 脚本)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 项目介绍 2.0 用户登录功能 3.0 用户管理功能 4.0 影院管理功能 5.0 电影管理功能 6.0 影厅管理功能 7.0 电影排片管理功能 8.0 用户评论管理功能 9.0 用户购票功…

【字符串匹配算法——BF算法】

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” 文章目录 BF算法介绍及过程演示代码实现过程下节预告KMP算法利用next数组存储子串中j回退的位置&#xff08;…

单幅图像合成 360° 3D 场景的新方法:PanoDreamer,可同时生成全景图像和相应的深度信息。

论文介绍了一种从单幅图像合成 360 3D 场景的新方法。该方法以连贯的方式生成全景图及其相应的深度&#xff0c;解决了现有最先进方法&#xff08;如 LucidDreamer 和 WonderJourney 的局限性。这些方法按照生成轨迹依次添加细节&#xff0c;通常在循环回输入图像时导致可见的接…

【蓝桥杯】46195.水仙花数

水仙花数 问题描述 打印所有100至999之间的水仙花数。所谓水仙花数是指满足其各位数字立方和为该数字本身的整数&#xff0c;例如 153135333。 样例输入 无 样例输出 153 370 371 407解题思路 遍历100到999之间的所有整数。对每个整数&#xff0c;计算其各位数字的立方和…

#思科模拟器通过服务配置保障无线网络安全Radius

演示拓扑图&#xff1a; 搭建拓扑时要注意&#xff1a; 只能连接它的Ethernet接口&#xff0c;不然会不通 MAC地址绑定 要求 &#xff1a;通过配置MAC地址过滤禁止非内部员工连接WiFi 打开无线路由器GUI界面&#xff0c;点开下图页面&#xff0c;配置路由器无线网络MAC地址过…

cpolar使用步骤

功能&#xff1a;内网穿透 下载地址&#xff1a;cpolar - secure introspectable tunnels to localhost 1 找到安装目录 2 进入命令行 目录处输入 cmd 3 验证 authtoken 不同用户 验证码不同。 注册后可以使用 cpolar.exe authtoken MzBlNzMwODktZjA3Yi00ZjJlLWJiMzQtNWU…

【排序算法】——插入排序

目录 前言 简介 基本思想 1.直接插入排序 2.希尔排序 代码实现 1.直接插入排序 2.希尔排序 总结 1.时空复杂度 2.稳定性 尾声 前言 排序(Sorting) 是计算机程序设计中的一种重要操作&#xff0c;它的功能是将一个数据元素&#xff08;或记录&#xff09;的任意序列&…

MySQL学习之DDL操作

目录 数据库的操作 创建 查看 选择 删除 修改 数据类型 表的创建 表的修改 表的约束 主键 PRIMARY KEY 唯一性约束 UNIQUE 非空约束 NOT NULL 外键约束 约束小结 索引 索引分类 常规索引 主键索引 唯一索引 外键索引 优点 缺点 视图 创建 删除 修改…

四、网络层:数据平面,《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》

文章目录 零、导论0.1 网络层服务0.2 网络层的关键功能0.3 网络层&#xff1a;数据平面、控制平面0.4 传统方式&#xff1a;每一路由器&#xff08;Per-router&#xff09;控制平面0.5 传统方式&#xff1a;路由和转发的相互作用0.6 SDN方式&#xff1a;逻辑集中的控制平面0.7 …

Java每日一题(1)

给定n个数a1,a2,...an,求它们两两相乘再相加的和。 即&#xff1a;Sa1*a2a1*a3...a1*ana2*a3...an-2*an-1an-2*anan-1*an 第一行输入的包含一个整数n。 第二行输入包含n个整数a1,a2,...an。 样例输入 4 1 3 6 9 样例输出 117 答案 import java.util.Scanner; // 1:无…

(2024.12自用存档)Ubuntu20.04——DynSLAM运行命令

前面忘记记录了&#xff0c;大概记一下后面 看了很多大佬的文章&#xff08;感谢&#xff01;&#xff09;&#xff0c;包括但不限于以下参考文章&#xff1a; Ubuntu16.04编译dynslam总结-CSDN博客 ubuntu14.04 CUDA8.0 DynSLAM编译与运行-CSDN博客 【视觉SLAM十四讲】Pa…

【阅读笔记】Android AMS forcestop停止应用

根据这篇文章作的笔记 基于Android 12的force-stop流程分析_android forcestop-CSDN博客 在AMS中&#xff0c;停止指定的应用是一个常用的功能&#xff0c;在代码里可以看到 Override 6806 public void forceStopPackage(final String packageName, int userId) { 6807 …

uniapp连接蓝牙操作(蓝牙设备地锁)

介绍&#xff1a; 本文采用uni-app框架来创建一个简单的用户界面&#xff0c;用于搜索、连接和发送命令给蓝牙设备。 1.打开蓝牙适配器 function openBluetooth() {uni.openBluetoothAdapter({success() {uni.offBluetoothDeviceFound();// 监听新设备发现事件uni.onBlueto…

《拉依达的嵌入式\驱动面试宝典》—前言目录篇

《拉依达的嵌入式\驱动面试宝典》—前言&目录篇 你好&#xff0c;我是拉依达。 感谢所有阅读关注我的同学支持&#xff0c;目前博客累计阅读 27w&#xff0c;关注1.5w人。其中博客《最全Linux驱动开发全流程详细解析&#xff08;持续更新&#xff09;-CSDN博客》已经是 Lin…

【博弈模型】古诺模型、stackelberg博弈模型、伯特兰德模型、价格领导模型

博弈模型 1、古诺模型&#xff08;cournot&#xff09;&#xff08;1&#xff09;假设&#xff08;2&#xff09;行为分析&#xff08;3&#xff09;经济后果&#xff08;4&#xff09;例题 2、stackelberg博弈模型&#xff08;产量领导模型&#xff09;&#xff08;1&#xff…

如何利用Python爬虫获得1688商品详情

在这个信息爆炸的时代&#xff0c;数据就像是一块块美味的奶酪&#xff0c;而爬虫就是我们手中的瑞士军刀。今天&#xff0c;我要带你一起潜入1688这个巨大的奶酪洞穴&#xff0c;用Python爬虫捞起那些香气四溢的商品详情。别担心&#xff0c;我们的工具箱里有各种各样的工具&a…

blender 制作莫比乌斯带

创建 Curve -> Cycle 在 Edit 模式下&#xff0c;选择&#xff1a; 选中两个点&#xff0c;按 delete 删除 Segment 如下选中&#xff1a; 选中最上面的点&#xff0c;然后按 E 将它拖到右边的点上。 按 R 旋转 90 度。 依次调整参数&#xff1a; 回到 Object 模式下&#x…

《云原生安全攻防》-- K8s安全框架:认证、鉴权与准入控制

从本节课程开始&#xff0c;我们将来介绍K8s安全框架&#xff0c;这是保障K8s集群安全比较关键的安全机制。接下来&#xff0c;让我们一起来探索K8s安全框架的运行机制。 在这个课程中&#xff0c;我们将学习以下内容&#xff1a; K8s安全框架&#xff1a;由认证、鉴权和准入控…

研华运动控制卡 (如PCI1245)单轴编辑路

问题描述: 单轴如何编辑路径&#xff1f; n 问题分析及处理办法– 步骤 在utility软件中&#xff0c;编辑路径和运行路径只能在多轴运动这个界面&#xff0c;而且&#xff0c;使用函数来加载路径Acm_GpLoadPath&#xff0c;也是需要多个轴 ​ 如果只运行一个轴&#xff0c;需…

LM芯片学习

1、LM7805稳压器 https://zhuanlan.zhihu.com/p/626577102?utm_campaignshareopn&utm_mediumsocial&utm_psn1852815231102873600&utm_sourcewechat_sessionhttps://zhuanlan.zhihu.com/p/626577102?utm_campaignshareopn&utm_mediumsocial&utm_psn18528…