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
表,字段有 id
、username
、age
,对应的实体类是:
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
表联查。表结构如下:
user
:id
,username
,age
order
:id
,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 一步到位。