Simplify Join Queries in MyBatis‑Plus with MPJ: A Hands‑On Guide
This tutorial shows how to use the MyBatis‑Plus‑Join (MPJ) extension to perform left‑join queries, modify mappers, build queries with MPJLambdaWrapper and MPJQueryWrapper, and add pagination, eliminating the need for manual XML SQL while improving development efficiency.
Import Dependencies
First add the required Maven dependencies. MPJ depends on a higher version of MyBatis‑Plus, so use the latest versions.
<code><dependency>
<groupId>com.github.yulichang</groupId>
<artifactId>mybatis-plus-join</artifactId>
<version>1.2.4</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency></code>Data Preparation
To demonstrate join queries, create three tables: orders, users (with name), and products (with name and unit price). The orders table references user_id and product_id.
Modify Mapper
Replace the MyBatis‑Plus BaseMapper with MPJBaseMapper in the mapper interfaces. Example:
<code>@Mapper
public interface OrderMapper extends MPJBaseMapper<Order> {
}
</code>Similarly modify the other mappers; services can optionally extend MPJBaseService and MPJBaseServiceImpl.
Query
MPJLambdaWrapper
Use MPJLambdaWrapper to build join queries without writing SQL. Example code:
<code>public void getOrder() {
List<OrderDto> list = orderMapper.selectJoinList(OrderDto.class,
new MPJLambdaWrapper<Order>()
.selectAll(Order.class)
.select(Product::getUnitPrice)
.selectAs(User::getName, OrderDto::getUserName)
.selectAs(Product::getName, OrderDto::getProductName)
.leftJoin(User.class, User::getId, Order::getUserId)
.leftJoin(Product.class, Product::getId, Order::getProductId)
.eq(Order::getStatus, 3));
list.forEach(System.out::println);
}
</code>The result shows fields from the related tables.
MPJQueryWrapper
MPJQueryWrapper offers a string‑based syntax similar to QueryWrapper. Example:
<code>public void getOrderSimple() {
List<OrderDto> list = orderMapper.selectJoinList(OrderDto.class,
new MPJQueryWrapper<Order>()
.selectAll(Order.class)
.select("t2.unit_price","t2.name as product_name")
.select("t1.name as user_name")
.leftJoin("t_user t1 on t1.id = t.user_id")
.leftJoin("t_product t2 on t2.id = t.product_id")
.eq("t.status","3"));
list.forEach(System.out::println);
}
</code>Note that table aliases t, t1, t2 are used instead of raw table names.
Pagination Query
MPJ also supports pagination via selectJoinPage. Add a MyBatis‑Plus pagination interceptor and use a Page object:
<code>@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
</code> <code>public void page() {
IPage<OrderDto> orderPage = orderMapper.selectJoinPage(
new Page<>(2, 10),
OrderDto.class,
new MPJLambdaWrapper<Order>()
.selectAll(Order.class)
.select(Product::getUnitPrice)
.selectAs(User::getName, OrderDto::getUserName)
.selectAs(Product::getName, OrderDto::getProductName)
.leftJoin(User.class, User::getId, Order::getUserId)
.leftJoin(Product.class, Product::getId, Order::getProductId)
.orderByAsc(Order::getId));
orderPage.getRecords().forEach(System.out::println);
}
</code>The generated SQL includes the appropriate LIMIT clause.
Conclusion
MPJ greatly simplifies join queries in MyBatis‑Plus, making it suitable for projects with moderate complexity and improving development efficiency. Some issues remain in the current version, which may be addressed in future releases.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.