Product Management Demo

Published 2026-07-30 20:15 Updated 2026-10-13 17:14 965 words 5 min read ... Page views AI-reviewed An AI proof-read this post, but it still deserves a careful read. AI-rewritten Someone else wrote the original; AI helped me rewrite and polish it.

AI-reviewed An AI proof-read this post, but it still deserves a careful read.

This article demonstrates the implementation of commodity and category paging association query based on Spring Boot, MyBatis-Plus, MySQL, and Druid. The basic code was generated through reverse engineering, the paging plug-in was configured and the associated query between the commodity table and the category table was realized. Finally, the correctness of the paging function and associated fields was verified through testing, and common problems such as SQL mapping errors, paging ineffectiveness, and field ambiguity were pointed out. solution.

Product Management Demo

This example uses Spring Boot,MyBatis-Plus, MySQL and Druid to implement paginated associated queries between goods and categories.

1. Prepare the database

create java2601 database and import goods.sql Table structure and test data in. The example requires at least the following two tables:

  • goods: Commodity list.
  • category: Commodity Category List.

in the commodity list cid Object used to associate category tables cid。

2. Create the Spring Boot project

Introduce dependence

in pom.xml Add the following dependencies to. The version number can be managed uniformly based on the Spring Boot version of the course project.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
        <version>3.5.6</version>
    </dependency>

    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-3-starter</artifactId>
        <version>1.2.23</version>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Configure data sources and MyBatis-Plus

in application.yml Configure database connections and MyBatis-Plus:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      url: jdbc:mysql://localhost:3306/java2601?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
      initial-size: 2
      min-idle: 3
      max-active: 10
      max-wait: 10000

mybatis-plus:
  mapper-locations: classpath*:/mapper/**/*.xml
  type-aliases-package: com.hyxy.goods.po
  configuration:
    map-underscore-to-camel-case: true
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: auto
      # table-prefix: tb_
      # logic-delete-field: deleteFlag
      # logic-delete-value: 1
      # logic-not-delete-value: 0

The development environment can directly write user names and passwords, and the actual project should manage database credentials through environment variables or external configuration.

create a directory structure

It is recommended to subcontract according to controller, business layer, data access layer, and entity classes.

image-001
image-001

Use reverse engineering to generate basic code

may be used MyBatis-Plus The code generator generates entity classes, Mappers, Services, and corresponding XML files.

image-002
image-002

After generation, you need to check the package name, table name, primary key policy, and storage location of the generated files. You cannot directly assume that all configurations are consistent with the current project.

3. Scan the Mapper interface

Using on the startup class @MapperScan, uniformly scan the Mapper interface:

package com.hyxy.goods;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.hyxy.goods.mapper")
public class GoodsApplication {

    public static void main(String[] args) {
        SpringApplication.run(GoodsApplication.class, args);
    }
}

use @MapperScan After that, there is usually no need to add it on each Mapper interface @Mapper。Just choose one of the two methods.

package com.hyxy.goods.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hyxy.goods.po.Category;

public interface CategoryMapper extends BaseMapper<Category> {
}
package com.hyxy.goods.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hyxy.goods.po.Goods;

public interface GoodsMapper extends BaseMapper<Goods> {
}

4. Configure paging plug-ins

in config Create a configuration class in the package and register it MyBatis-Plus Page Interceptors:

package com.hyxy.goods.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

Use of this courseware MyBatis-Plus 3.5.6。If you upgrade to 3.5.9 Or higher, the parser related to paging plug-in has been split into optional dependencies, and modules need to be supplemented according to the official instructions of the corresponding version.

When querying products, the category name is also displayed.

Add non-table fields to the commodity entity class

cname From related query, not goods Table, so you need to use the @TableField(exist = false):

package com.hyxy.goods.po;

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

@Data
public class Goods {

    // 省略 goods 表中的其他字段

    @TableField(exist = false)
    private String cname;
}

Declare query methods in the Mapper interface

Paging parameters should be placed before the method parameter list, and query criteria should be used @Param Explicit naming:

package com.hyxy.goods.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hyxy.goods.po.Goods;
import org.apache.ibatis.annotations.Param;

public interface GoodsMapper extends BaseMapper<Goods> {

    IPage<Goods> selectJoinCategory(
            Page<Goods> page,
            @Param("gname") String gname,
            @Param("cid") Integer cid
    );
}

Writing Mapper XML

in resources/mapper Create under the directory GoodsMapper.xml。namespace Must be consistent with the fully qualified class name of the Mapper interface.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hyxy.goods.mapper.GoodsMapper">

    <select id="selectJoinCategory" resultType="Goods">
        SELECT
            g.gid,
            g.gname,
            g.price,
            g.stock,
            g.cid,
            g.sales,
            g.onsale,
            g.createtime,
            c.cname AS cname
        FROM goods AS g
        LEFT JOIN category AS c ON g.cid = c.cid
        <where>
            <if test="gname != null and gname != ''">
                AND g.gname LIKE CONCAT('%', #{gname}, '%')
            </if>
            <if test="cid != null">
                AND g.cid = #{cid}
            </if>
        </where>
        ORDER BY g.gid DESC
    </select>

</mapper>

Table aliases should be added to columns in associated queries as much as possible to avoid ambiguity when two tables have fields with the same name.

6. Writing tests

Use the Spring Boot test class to verify paging and association query results:

package com.hyxy.goods;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hyxy.goods.mapper.GoodsMapper;
import com.hyxy.goods.po.Goods;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class GoodsApplicationTests {

    @Resource
    private GoodsMapper goodsMapper;

    @Test
    void selectJoinCategory() {
        Page<Goods> page = new Page<>(1, 3);

        IPage<Goods> pageResult = goodsMapper.selectJoinCategory(
                page,
                null,
                null
        );

        pageResult.getRecords().forEach(System.out::println);
        System.out.println("总记录数:" + pageResult.getTotal());
        System.out.println("总页数:" + pageResult.getPages());
    }
}

During testing, you should confirm that the console generates SQL with paging restrictions and check the cname Whether the mapping is correct.

7. Common questions

Mapper method cannot find corresponding SQL

Check the following:

  • of XML namespace Whether it is consistent with the fully qualified name of the Mapper interface.
  • <select> the id Whether it is consistent with the interface method name.
  • mapper-locations Whether to overwrite the directory where the XML file is located.

Pagination does not take effect

Confirm that you have registered MybatisPlusInterceptor and PaginationInnerInterceptor, and ensure that paging parameters are in front of the Mapper method parameter list.

Error reported in category number condition or abnormal query result

Using in multi-table queries g.cid, don’t write directly without table aliases cid, otherwise field ambiguity may occur.

Written by AI-rewritten

If you enjoyed this, leave a comment~

Loading...