You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot关联映射存null及MapStruct Bean缺失问题求助

问题解决:Spring Boot关联字段保存为null与MapStruct Bean找不到

一、产品关联分类保存为null的问题

问题原因

BeanUtils.copyProperties无法自动将CategoryDto实例转换为CategoryModel实例(二者为不同类型对象),导致ProductModel的category字段始终为null,即使请求中传入了正确的category_id。

解决方案

方案1:手动处理关联(快速修复)

在ProductController的saveProduct方法中,先通过category_id从数据库查询对应的CategoryModel,再绑定到ProductModel:

@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
@RequestMapping("/product")
public class ProductController {

    final ProductService productService;
    final CategoryService categoryService; // 新增注入CategoryService

    public ProductController (ProductService productService, CategoryService categoryService) {
        this.productService = productService;
        this.categoryService = categoryService;
    }

    @PostMapping
    public ResponseEntity<Object> saveProduct (@RequestBody @Valid ProductDto productDto) {
        var productModel = new ProductModel();
        BeanUtils.copyProperties(productDto, productModel);
        
        // 通过CategoryDto的id查询对应分类实体
        UUID categoryId = productDto.getCategory().getId();
        CategoryModel category = categoryService.findById(categoryId)
                .orElseThrow(() -> new RuntimeException("分类不存在,ID:" + categoryId));
        productModel.setCategory(category);
        
        return ResponseEntity.status(HttpStatus.CREATED).body(productService.save(productModel));
    }
}

注意:需确保CategoryService实现了findById方法,用于从数据库查询分类。

方案2:优化DTO设计(简化请求)

修改ProductDto,直接接收UUID类型的categoryId而非整个CategoryDto,让请求更简洁:

public class ProductDto {
    @NotBlank
    private String product;

    private String description;

    @DecimalMin(value = "0.01", inclusive = true)
    private Float price;

    @NotNull
    @Min(value = 0, message = "库存不能小于{value}")
    private Integer stock;

    @NotNull
    private UUID categoryId; // 替换原有的CategoryDto category

    // 省略原有getter/setter,新增categoryId的getter/setter
    public UUID getCategoryId() {
        return categoryId;
    }

    public void setCategoryId(UUID categoryId) {
        this.categoryId = categoryId;
    }
}

对应的Controller代码调整:

@PostMapping
public ResponseEntity<Object> saveProduct (@RequestBody @Valid ProductDto productDto) {
    var productModel = new ProductModel();
    BeanUtils.copyProperties(productDto, productModel);
    
    CategoryModel category = categoryService.findById(productDto.getCategoryId())
            .orElseThrow(() -> new RuntimeException("分类不存在"));
    productModel.setCategory(category);
    
    return ResponseEntity.status(HttpStatus.CREATED).body(productService.save(productModel));
}

Postman请求体示例:

{
    "product": "测试商品",
    "description": "测试描述",
    "price": 29.99,
    "stock": 20,
    "categoryId": "你的分类UUID"
}

二、MapStruct的CategoryMapper Bean找不到的启动错误

问题原因

  • MapStruct接口未配置为Spring管理的Bean,导致Spring无法扫描识别;
  • 依赖或注解处理器配置不完整,导致MapStruct未生成对应的实现类。

解决方案

步骤1:正确配置MapStruct Mapper接口

在CategoryMapper接口上添加@Mapper注解,并指定componentModel = "spring",让MapStruct生成Spring Bean:

import org.mapstruct.Mapper;

@Mapper(componentModel = "spring") // 关键:指定Spring组件模型
public interface CategoryMapper {
    // 定义转换方法
    CategoryModel toModel(CategoryDto categoryDto);
    CategoryDto toDto(CategoryModel categoryModel);
}

步骤2:完善依赖与注解处理器配置

Maven项目(pom.xml)
<dependencies>
    <!-- MapStruct核心依赖 -->
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.5.5.Final</version>
    </dependency>
    <!-- Lombok(如果使用) -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>17</source> <!-- 匹配你的JDK版本 -->
                <target>17</target>
                <annotationProcessorPaths>
                    <!-- MapStruct注解处理器 -->
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>1.5.5.Final</version>
                    </path>
                    <!-- Lombok注解处理器(如果使用) -->
                    <path>
                        <groupId>org.projectlombok</groupId>
                        <artifactId>lombok</artifactId>
                        <version>1.18.30</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
Gradle项目(build.gradle)
plugins {
    id 'java'
    id 'org.springframework.boot' version '3.2.0'
    id 'io.spring.dependency-management' version '1.1.4'
}

dependencies {
    implementation 'org.mapstruct:mapstruct:1.5.5.Final'
    annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final'
    // Lombok(如果使用)
    implementation 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
}

步骤3:清理重建项目

  • Maven执行:mvn clean install
  • Gradle执行:gradle clean build
  • 重启Spring Boot应用,Spring即可扫描到MapStruct生成的CategoryMapper Bean。

内容的提问来源于stack exchange,提问作者Routfin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 14:31:30