MyBatis-Plus 自定义 SQL 和复杂查询

MyBatis-Plus 自定义 SQL 和复杂查询详解

MyBatis-Plus 是 MyBatis 的增强版,提供了许多开箱即用的 CRUD 操作。然而,在实际项目中,开发者常常需要编写自定义 SQL 以处理更复杂的查询需求。MyBatis-Plus 提供了灵活的机制,允许开发者通过注解或 XML 自定义 SQL,同时也能支持复杂查询、动态 SQL 等高级操作。


1. 自定义 SQL 的两种方式

MyBatis-Plus 支持两种自定义 SQL 的方式:

  1. 注解方式 :直接在 Mapper 接口上通过注解编写 SQL 语句。
  2. XML 方式 :通过 Mapper 配置文件的方式编写自定义 SQL。

2. 通过注解编写自定义 SQL

MyBatis-Plus 支持在 Mapper 接口方法上直接使用注解编写 SQL 语句。常见的注解包括:

  • @Select:用于查询。
  • @Insert:用于插入。
  • @Update:用于更新。
  • @Delete:用于删除。
2.1 查询示例

假设有一个 User 表,包含 idusernameemail 字段。通过注解编写自定义 SQL 查询用户信息:

复制代码
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.model.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface UserMapper extends BaseMapper<User> {

    // 根据用户名查询用户
    @Select("SELECT * FROM user WHERE username = #{username}")
    User findByUsername(String username);

    // 查询所有用户
    @Select("SELECT * FROM user")
    List<User> findAll();
}
2.2 插入示例

通过注解实现插入用户记录:

复制代码
import org.apache.ibatis.annotations.Insert;

@Mapper
public interface UserMapper extends BaseMapper<User> {

    @Insert("INSERT INTO user (username, email) VALUES (#{username}, #{email})")
    void insertUser(User user);
}
2.3 动态 SQL

MyBatis-Plus 还支持通过 @SelectProvider@UpdateProvider 等注解来实现动态 SQL。以下是通过 @SelectProvider 动态生成查询 SQL 的示例:

复制代码
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.builder.annotation.ProviderContext;
import java.util.Map;

@Mapper
public interface UserMapper extends BaseMapper<User> {

    @SelectProvider(type = SqlProvider.class, method = "findByCondition")
    List<User> findByCondition(Map<String, Object> conditions);

    class SqlProvider {
        public String findByCondition(Map<String, Object> params, ProviderContext context) {
            StringBuilder sql = new StringBuilder("SELECT * FROM user WHERE 1=1");
            if (params.get("username") != null) {
                sql.append(" AND username = #{username}");
            }
            if (params.get("email") != null) {
                sql.append(" AND email = #{email}");
            }
            return sql.toString();
        }
    }
}

在此示例中,通过 @SelectProvider 动态生成 SQL,根据传入的条件查询用户。


3. 通过 XML 编写自定义 SQL

除了注解方式,MyBatis-Plus 还支持通过 XML 文件编写自定义 SQL。XML 配置的方式可以编写更复杂、灵活的查询和动态 SQL。

3.1 XML 配置基本结构

首先,在 resources/mapper/ 目录下创建 UserMapper.xml,并通过 namespace 绑定 UserMapper 接口。

复制代码
<?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">

    <!-- 查询所有用户 -->
    <select id="findAll" resultType="com.example.demo.model.User">
        SELECT * FROM user
    </select>

    <!-- 根据用户名查询用户 -->
    <select id="findByUsername" resultType="com.example.demo.model.User">
        SELECT * FROM user WHERE username = #{username}
    </select>

    <!-- 插入用户 -->
    <insert id="insertUser">
        INSERT INTO user (username, email) VALUES (#{username}, #{email})
    </insert>

</mapper>
3.2 XML 动态 SQL 示例

MyBatis 的动态 SQL 标签可以用于构建灵活的 SQL 语句,常见的动态 SQL 标签有:

  • <if>:根据条件拼接 SQL。
  • <choose>:类似于 switch-case
  • <where>:智能拼接条件。
  • <foreach>:用于处理集合(如 IN 查询)。

以下示例展示如何使用动态 SQL 实现根据条件查询用户:

复制代码
<select id="findByCondition" resultType="com.example.demo.model.User">
    SELECT * FROM user
    <where>
        <if test="username != null">
            AND username = #{username}
        </if>
        <if test="email != null">
            AND email = #{email}
        </if>
    </where>
</select>

4. 复杂查询的实现

在实际开发中,复杂查询经常涉及多表关联查询、分页、动态条件查询等。MyBatis-Plus 提供了良好的支持,结合 SQL 注解、XML 和查询构造器等机制,可以实现灵活的复杂查询。

4.1 多表关联查询

MyBatis-Plus 支持通过自定义 SQL 实现多表关联查询(如 JOIN 查询)。

复制代码
<select id="findUserWithRole" resultType="com.example.demo.model.User">
    SELECT u.id, u.username, r.role_name
    FROM user u
    LEFT JOIN role r ON u.role_id = r.id
    WHERE u.id = #{id}
</select>

在此示例中,user 表通过 role_id 关联 role 表,查询用户的角色信息。

4.2 动态分页查询

结合 MyBatis-Plus 提供的分页插件和动态 SQL,可以实现复杂的分页查询。首先,需要引入分页插件:

复制代码
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MyBatisPlusConfig {

    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }
}

然后在 UserMapper.xml 中实现分页查询:

复制代码
<select id="findByCondition" resultType="com.example.demo.model.User">
    SELECT * FROM user
    <where>
        <if test="username != null">
            AND username = #{username}
        </if>
        <if test="email != null">
            AND email = #{email}
        </if>
    </where>
</select>

在服务层调用时使用分页功能:

复制代码
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public Page<User> findUsersByCondition(Page<User> page, Map<String, Object> conditions) {
        return userMapper.findByCondition(page, conditions);
    }
}

5. 使用查询构造器进行复杂查询

MyBatis-Plus 提供了一个查询构造器 Wrapper,用于简化条件查询。常见的查询构造器有:

  • QueryWrapper:用于构建查询条件。
  • UpdateWrapper:用于构建更新条件。
5.1 使用 QueryWrapper 进行复杂查询

QueryWrapper 是 MyBatis-Plus 提供的条件构造器,允许开发者使用链式语法构建查询条件。

复制代码
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public List<User> findUsersByCondition(String username, String email) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(username != null, "username", username)
                    .like(email != null, "email", email);
        return userMapper.selectList(queryWrapper);
    }
}

在此示例中,QueryWrapper 用于根据条件动态构建 SQL 查询,eqlike 方法会根据传入的参数生成相应的 SQL 语句。

5.2 使用 UpdateWrapper 进行复杂更新

类似于查询,UpdateWrapper 用于构建更新条件。

复制代码
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;

public

 void updateUserEmail(Integer id, String email) {
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.eq("id", id).set("email", email);
    userMapper.update(null, updateWrapper);
}

6. 总结

MyBatis-Plus 提供了灵活的自定义 SQL 和复杂查询机制,支持通过注解、XML 和查询构造器实现灵活的数据库操作。

  • 注解方式:简单、直观,适合快速开发常见的 SQL 操作。
  • XML 方式:适用于复杂 SQL 和动态 SQL,通过 MyBatis 提供的标签,可以灵活地编写条件查询、多表关联查询等。
  • 查询构造器 :通过 QueryWrapperUpdateWrapper,开发者可以以链式语法构建复杂查询条件。
相关推荐
CHEN5_021 分钟前
【Java面试题】缓存穿透
java·开发语言·数据库·redis·缓存
_码农1213829 分钟前
使用mybatis生成器生成实体类mapper和查询参数文件,简单spring mvc 项目。使用log4j输出日志到控制台和文件中。使用配置文件注册Bean
spring·mvc·mybatis
卍郝凝卍29 分钟前
云服务器数据库
运维·服务器·数据库
不辉放弃34 分钟前
Spark SQL 的详细介绍
数据库·pyspark·大数据开发·sparksql
zc.z2 小时前
Tomcat线程池、业务线程池与数据库连接池的层级约束关系解析及配置优化
服务器·数据库·tomcat
Aplis2 小时前
ETCD学习之路
数据库·学习·etcd
拷斤锟2 小时前
使用Excel解析从OData API获取到的JSON数据
数据库·json·excel
翔云1234562 小时前
MySQL 高并发下如何保证事务提交的绝对顺序?
数据库·mysql
正在走向自律2 小时前
X2Doris是SelectDB可视化数据迁移工具,安装与部署&使用手册,轻松进行大数据迁移
数据库·数据迁移·selectdb·x2doris·数据库迁移工具
tuokuac2 小时前
SQL中的LEFT JOIN
数据库·sql