Backend Development 8 min read

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.

macrozheng
macrozheng
macrozheng
Simplify Join Queries in MyBatis‑Plus with MPJ: A Hands‑On Guide

Import Dependencies

First add the required Maven dependencies. MPJ depends on a higher version of MyBatis‑Plus, so use the latest versions.

<code>&lt;dependency&gt;
    &lt;groupId&gt;com.github.yulichang&lt;/groupId&gt;
    &lt;artifactId&gt;mybatis-plus-join&lt;/artifactId&gt;
    &lt;version&gt;1.2.4&lt;/version&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;com.baomidou&lt;/groupId&gt;
    &lt;artifactId&gt;mybatis-plus-boot-starter&lt;/artifactId&gt;
    &lt;version&gt;3.5.1&lt;/version&gt;
&lt;/dependency&gt;</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.

JavaORMpaginationMyBatis-PlusJoin QueryMPJ
macrozheng
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.