MyBatis-Plus 常见 API 实战:从基础到多表联查


MyBatis-Plus 常见 API 实战:从基础到多表联查

MyBatis-Plus(简称 MP)是个好东西,基于 MyBatis 做了不少封装,能省下不少 CRUD 的重复代码。今天咱们就来聊聊它的常见 API,顺便结合多表联查的场景,带点代码实战,帮你快速上手。

1. MyBatis-Plus 是个啥?

简单说,MyBatis-Plus 是 MyBatis 的增强版,自带了通用 Mapper 和 Service,常见的增删改查都不用自己写 SQL。它还支持条件构造器、自动填充等功能,用起来挺顺手。咱们先从基础 API 开始,然后再搞个多表联查的例子。

2. 环境准备

先搭个基础环境,假设你用的是 Spring Boot + MySQL,项目里加个依赖:

xml 复制代码
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
</dependency>

配置文件(application.yml)里配上数据源:

yaml 复制代码
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=UTF-8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

3. 常见 API 实战

假设我们有个 User 表,字段有 idusernameage,对应的实体类是:

java 复制代码
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("user")
public class User {
    private Long id;
    private String username;
    private Integer age;
}

Mapper 接口直接继承 BaseMapper,啥都不用写:

java 复制代码
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface UserMapper extends BaseMapper<User> {
}
3.1 增:插入数据

insert 方法,简单粗暴:

java 复制代码
@SpringBootTest
class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    void testInsert() {
        User user = new User();
        user.setUsername("张三");
        user.setAge(25);
        userMapper.insert(user);
        System.out.println("新用户 ID: " + user.getId());
    }
}

跑完这条,数据库里就多了一条记录,id 还能自动回填,前提是你表里设置了主键自增。

3.2 删:删除数据

删数据可以用 deleteById 或条件构造器:

java 复制代码
@Test
void testDelete() {
    // 按 ID 删
    userMapper.deleteById(1L);

    // 条件删,比如 age > 30 的
    userMapper.delete(new QueryWrapper<User>().gt("age", 30));
    System.out.println("删了几条老家伙");
}

条件构造器 QueryWrapper 是 MP 的亮点,后面多表联查还会用到。

3.3 改:更新数据

更新可以用 updateById 或条件更新:

java 复制代码
@Test
void testUpdate() {
    // 按 ID 改
    User user = new User();
    user.setId(2L);
    user.setUsername("李四");
    userMapper.updateById(user);

    // 条件改,把 age < 20 的都改成 18
    userMapper.update(null, new UpdateWrapper<User>()
        .lt("age", 20)
        .set("age", 18));
    System.out.println("小年轻都变18了");
}
3.4 查:查询数据

查询方法贼多,咱们挑几个常用的:

java 复制代码
@Test
void testSelect() {
    // 按 ID 查
    User user = userMapper.selectById(2L);
    System.out.println("查到的人: " + user);

    // 条件查,比如 age 在 20-30 之间的
    List<User> users = userMapper.selectList(new QueryWrapper<User>()
        .between("age", 20, 30));
    users.forEach(System.out::println);

    // 分页查
    Page<User> page = new Page<>(1, 2); // 第1页,每页2条
    userMapper.selectPage(page, null);
    System.out.println("总条数: " + page.getTotal());
    page.getRecords().forEach(System.out::println);
}

分页得加个配置类,不然不生效:

java 复制代码
@Configuration
public class MyBatisPlusConfig {
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

4. 多表联查实战

光玩单表不过瘾,咱们加个 Order 表,和 User 表联查。表结构如下:

  • userid, username, age
  • orderid, user_id, order_name

对应的实体类:

java 复制代码
@Data
@TableName("order")
public class Order {
    private Long id;
    private Long userId;
    private String orderName;
}

Order 的 Mapper:

java 复制代码
public interface OrderMapper extends BaseMapper<Order> {
}

需求:查出所有用户和他们的订单信息。MP 不像 MyBatis 那样直接写 SQL,但可以用 QueryWrapper 或自定义 SQL。

4.1 用 QueryWrapper 实现联查

直接在代码里拼条件:

java 复制代码
@SpringBootTest
class MultiTableTest {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private OrderMapper orderMapper;

    @Test
    void testJoin() {
        // 先查所有用户
        List<User> users = userMapper.selectList(null);
        // 再根据 user_id 查订单
        for (User user : users) {
            List<Order> orders = orderMapper.selectList(new QueryWrapper<Order>()
                .eq("user_id", user.getId()));
            System.out.println(user.getUsername() + " 的订单:");
            orders.forEach(order -> System.out.println(order.getOrderName()));
        }
    }
}

这种方式简单,但得查两次数据库,性能差点。

4.2 自定义 SQL 实现联查

MP 支持在 Mapper 里写自定义 SQL,用注解 @Select

java 复制代码
public interface UserMapper extends BaseMapper<User> {
    @Select("SELECT u.*, o.order_name FROM user u LEFT JOIN `order` o ON u.id = o.user_id")
    List<Map<String, Object>> selectUserWithOrders();
}

测试一下:

java 复制代码
@Test
void testCustomJoin() {
    List<Map<String, Object>> result = userMapper.selectUserWithOrders();
    result.forEach(System.out::println);
}

输出可能是:

ini 复制代码
{id=1, username=张三, age=25, order_name=手机}
{id=2, username=李四, age=30, order_name=电脑}

这种方式一次查询搞定,效率更高。返回 Map 比较灵活,要是想直接映射到实体,可以定义个 VO 类:

java 复制代码
@Data
public class UserOrderVO {
    private Long id;
    private String username;
    private Integer age;
    private String orderName;
}

@Select("SELECT u.*, o.order_name FROM user u LEFT JOIN `order` o ON u.id = o.user_id")
List<UserOrderVO> selectUserWithOrdersVO();

5. 小结

MyBatis-Plus 的 API 用起来真挺爽,增删改查都不用手写 SQL,条件构造器还能灵活拼条件。单表操作靠 BaseMapper 就够了,多表联查稍微麻烦点,可以用两次查询凑合,也能写自定义 SQL 一步到位。

相关推荐
Studying_swz32 分钟前
Spring WebFlux之流式输出
java·后端·spring
苏墨瀚34 分钟前
C#语言的响应式设计
开发语言·后端·golang
苏墨瀚2 小时前
SQL语言的散点图
开发语言·后端·golang
一只韩非子7 小时前
一句话告诉你什么叫编程语言自举!
前端·javascript·后端
沈二到不行8 小时前
多头注意力&位置编码:完型填空任务
人工智能·后端·deepseek
追逐时光者8 小时前
C# 中比较实用的关键字,基础高频面试题!
后端·c#·.net
GoGeekBaird8 小时前
一文搞懂:Anthropic发布MCP重要更新,告别长连接
后端·操作系统
Asthenia04128 小时前
面试问题分析:为什么Java能实现反射机制,其他语言不行?
后端
拳布离手9 小时前
fastgpt工作流探索
后端
Asthenia04129 小时前
IO 多路复用详解:从概念->系统调用-> Java 在NIO中实现
后端