MyBatis-Plus-Join 指南

功能特点

  • 简化多表操作MyBatis-Plus-JoinMyBatis-Plus 的扩展,让开发者能更便捷地进行多表关联查询、子查询等操作,通过简洁的API满足复杂查询需求。例如,在进行多表联合查询时,无需编写大量复杂的SQL语句或配置文件,只需简单配置和调用相关方法,即可实现多表数据的关联查询。
  • 支持多种特性:支持列枚举、别名、逻辑删除、TypeHandle、一对一、一对多等功能,还支持 Lambda 和字符串两种查询方式,以及自定义字段映射和结果转换、动态条件构造和链式调用等高级特性。比如,在进行数据查询时,可以根据不同的条件动态构造查询语句,灵活地实现各种复杂的查询逻辑。
  • 兼容性好:作为 MyBatis-Plus 的插件,它完全兼容 MyBatis-Plus 的使用习惯,引入后不会对现有工程产生影响,能与 MyBatis-Plus 原有功能无缝集成。

依赖配置

以Maven项目为例,在pom.xml文件中添加以下依赖即可使用:

<dependency>
    <groupId>com.github.yulichang</groupId>
    <artifactId>mybatis-plus-join-boot-starter</artifactId>
    <version>1.5.3</version>
</dependency>

最新版 MyBatis-Plus-Join 需要配合 MyBatis-Plus 3.1.2 及以上的版本使用。

代码示例

假设存在用户表 user 和订单表 order,它们之间通过 user_id 关联,以下是使用 mybatis-plus-join-boot-starter 进行多表查询的示例:

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.yulichang.base.MPJBaseMapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.example.demo.entity.User;
import com.example.demo.entity.Order;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.util.List;

@Repository
public class UserRepository {

    @Resource
    private MPJBaseMapper<User> userMapper;

    public List<User> getUserWithOrders() {
        // 使用MPJLambdaWrapper进行多表查询
        MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<User>()
               .selectAll(User.class)
               .select(Order::getOrderId, Order::getOrderName)
               .leftJoin(Order.class, Order::getUserId, User::getUserId);

        return userMapper.selectList(wrapper);
    }
}

在上述代码中,通过 MPJLambdaWrapper 进行多表关联查询,先选择 User 表的所有字段,再选择 Order 表的 orderIdorderName 字段,然后通过 leftJoin 方法进行左连接,指定连接条件是 Order 表的 userIdUser 表的 userId 相等。最后通过 userMapper.selectList(wrapper) 执行查询,获取包含关联订单信息的用户列表。

完整示例

以下是一个使用 mybatis-plus-join-boot-starter 进行多表关联查询的完整代码示例,假设我们有一个简单的业务场景:用户表 user 和订单表 order,用户可以有多个订单,我们要查询出每个用户及其对应的订单信息。

1、引入依赖

pom.xml 文件中添加相关依赖:

<dependencies>
    <!-- Spring Boot 启动器 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <!-- MyBatis-Plus 启动器 -->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>最新版本</version>
    </dependency>
    <!-- mybatis-plus-join-boot-starter -->
    <dependency>
        <groupId>com.github.yulichang</groupId>
        <artifactId>mybatis-plus-join-boot-starter</artifactId>
        <version>最新版本</version>
    </dependency>
    <!-- MySQL 驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
</dependencies>

请将 最新版本 替换为实际的最新版本号。

2、配置数据源和 MyBatis-Plus

application.yml 文件中配置数据源和 MyBatis-Plus 相关信息:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: your_username
    password: your_password
    driver-class-name: com.mysql.cj.jdbc.Driver

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

your_databaseyour_usernameyour_password 替换为实际的数据库名称、用户名和密码。

3、定义实体类

User 实体类:

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;
import java.util.List;

@Data
@TableName("user")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId
    private Long id;

    private String username;

    private String password;

    @TableField(exist = false)
    private List<Order> orders;
}

Order 实体类:

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

@Data
@TableName("order")
public class Order implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId
    private Long id;

    private Long userId;

    private String orderNo;

    private Double totalPrice;

    @TableField(exist = false)
    private User user;
}

4、编写 Mapper 接口

UserMapper 接口:

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.github.yulichang.base.MPJBaseMapper;
import com.example.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User>, MPJBaseMapper<User> {
}

OrderMapper 接口:

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.github.yulichang.base.MPJBaseMapper;
import com.example.entity.Order;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface OrderMapper extends BaseMapper<Order>, MPJBaseMapper<Order> {
}

5、编写业务逻辑

UserService 中进行多表关联查询:

import com.baomidou.mybatisplus.core.conditions.query.MPJLambdaWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.Order;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserService extends ServiceImpl<UserMapper, User> {

    public List<User> getUserWithOrders() {
        MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<User>()
               .selectAll(User.class)
               .select(Order::getId, Order::getOrderNo, Order::getTotalPrice)
               .leftJoin(Order.class, Order::getUserId, User::getId);

        return baseMapper.selectList(wrapper);
    }
}

6、测试代码

在测试类中调用业务方法进行测试:

import com.example.service.UserService;
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 UserServiceTest {

    @Autowired
    private UserService userService;

    @Test
    public void testGetUserWithOrders() {
        List<User> userList = userService.getUserWithOrders();
        for (User user : userList) {
            System.out.println("用户: " + user.getUsername);
            for (Order order : user.getOrders()) {
                System.out.println("  订单号: " + order.getOrderNo + ", 总价: " + order.getTotalPrice);
            }
        }
    }
}

Ref:https://www.lifengdi.com/archives/article/4328