商品管理 Demo
本示例使用 Spring Boot、MyBatis-Plus、MySQL 和 Druid,实现商品与类别的分页关联查询。
一、准备数据库
创建 java2601 数据库,并导入 goods.sql 中的表结构和测试数据。示例至少需要以下两张表:
goods:商品表。category:商品类别表。
商品表中的 cid 用于关联类别表的 cid。
二、创建 Spring Boot 工程
引入依赖
在 pom.xml 中加入以下依赖。版本号可根据课程项目的 Spring Boot 版本统一管理。
<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>配置数据源和 MyBatis-Plus
在 application.yml 中配置数据库连接和 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开发环境可以直接写用户名和密码,实际项目应通过环境变量或外部配置管理数据库凭据。
创建目录结构
建议按照控制器、业务层、数据访问层和实体类分包。

使用逆向工程生成基础代码
可以使用 MyBatis-Plus 代码生成器生成实体类、Mapper、Service 和对应 XML 文件。

生成后需要检查包名、表名、主键策略以及生成文件的保存位置,不能直接假定所有配置都符合当前项目。
三、扫描 Mapper 接口
在启动类上使用 @MapperScan,统一扫描 Mapper 接口:
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);
}
}使用 @MapperScan 后,通常不需要再在每个 Mapper 接口上添加 @Mapper。两种方式选择一种即可。
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> {
}
四、配置分页插件
在 config 包中创建配置类,并注册 MyBatis-Plus 分页拦截器:
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;
}
}本课件使用 MyBatis-Plus 3.5.6。若升级到 3.5.9 或更高版本,分页插件相关解析器已拆分为可选依赖,需要按照对应版本的官方说明补充模块。
五、实现商品与类别的关联查询
查询商品时,同时显示所属类别名称。
在商品实体类中添加非表字段
cname 来自关联查询,不是 goods 表中的真实字段,因此需要使用 @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;
}在 Mapper 接口中声明查询方法
分页参数应放在方法参数列表前面,查询条件使用 @Param 显式命名:
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
);
}编写 Mapper XML
在 resources/mapper 目录下创建 GoodsMapper.xml。namespace 必须与 Mapper 接口的全限定类名一致。
<?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>关联查询中的列应尽量添加表别名,避免两张表存在同名字段时产生歧义。
六、编写测试
使用 Spring Boot 测试类验证分页和关联查询结果:
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());
}
}测试时应确认控制台生成了带分页限制的 SQL,并检查每个商品对象中的 cname 是否正确映射。
七、常见问题
Mapper 方法找不到对应 SQL
检查以下内容:
- XML 的
namespace是否与 Mapper 接口全限定名一致。 <select>的id是否与接口方法名一致。mapper-locations是否覆盖 XML 文件所在目录。
分页不生效
确认已经注册 MybatisPlusInterceptor 和 PaginationInnerInterceptor,并保证分页参数位于 Mapper 方法参数列表前面。
类别编号条件报错或查询结果异常
在多表查询中使用 g.cid,不要直接写没有表别名的 cid,否则可能出现字段歧义。
喜欢的话,留下你的评论吧~