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

Spring Boot3+Java17中Lombok与MapStruct属性映射错误排查

问题

编译报错如下:

19:48
C:\Users\xxxxx\Documents\workspace\eshop\src\main\java\com\eshop\mapper\ProductMapper.java:19:48
java: No property named "product.name" exists in source parameter(s). Did you mean "null"?
C:\Users\xxxxx\Documents\workspace\eshop\src\main\java\com\eshop\mapper\ProductMapper.java:20:55
java: No property named "product.description" exists in source parameter(s). Did you mean "null"?
C:\Users\xxxxx\Documents\workspace\eshop\src\main\java\com\eshop\mapper\ProductMapper.java:21:53
java: No property named "product.id" exists in source parameter(s). Did you mean "null"?

相关代码

ProductMapper

package com.eshop.mapper;

import com.eshop.domain.entity.Product;
import com.eshop.domain.entity.ProductVariant;
import com.eshop.dto.request.body.ProductCreationBody;
import com.eshop.dto.request.response.ProductGetDetailsResponse;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;

import java.util.List;

@Mapper(componentModel = "spring")
public interface ProductMapper {

    ProductGetDetailsResponse map(Product product);

    @Mappings({
            @Mapping(target = "name", source = "product.name"),
            @Mapping(target = "description", source = "product.description"),
            @Mapping(target = "productId", source = "product.id"),
    })
    ProductGetDetailsResponse map(ProductVariant productVariant);

    Product map(ProductCreationBody productCreationRequestBody);

    List<ProductGetDetailsResponse> map(List<ProductVariant> products);
}

待映射对象

ProductGetDetailsResponse

package com.eshop.dto.request.response;

import lombok.*;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class ProductGetDetailsResponse {

    private Long id;

    private Long productId;

    private String name;

    private String description;

    private String imageUrl;

    private String color;

    private String size;

    private String price;

    private String discount;

    private String displayOrder;
}

ProductVariant实体类

package com.eshop.domain.entity;

import com.eshop.domain.enums.ProductGender;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.io.Serializable;
import java.time.LocalDate;

@Entity
@Table(name = "product_variant", uniqueConstraints = {
        @UniqueConstraint(columnNames = {"product_id", "productColor", "productSize"})
})
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class ProductVariant implements Serializable {

    private static final Long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Enumerated(EnumType.STRING)
    private ProductGender productGender;

    private String productColor;

    private String productSize;

    private Integer unitsInStock;

    private String imageUrl;

    private Double price;

    private Integer discount;

    private LocalDate discountStartDate;

    private LocalDate discountEndDate;

    private Integer displayOrder;

    @ManyToOne
    @JoinColumn(name = "product_id")
    private Product product;
}

Product实体类

package com.eshop.domain.entity;

import com.eshop.domain.enums.ProductStatus;
import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.io.Serializable;
import java.util.Date;
import java.util.Set;

@Table(name = "products", uniqueConstraints = {
        @UniqueConstraint(columnNames = "name")
})
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Product implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true)
    private String name;

    private String description;

    @Enumerated(EnumType.STRING)
    private ProductStatus status;

    @ManyToOne
    @JoinColumn(name = "store_id")
    private Store store;

    @CreationTimestamp
    @Column(name = "created_at")
    private Date createdAt;

    @UpdateTimestamp
    @Column(name = "updated_at")
    private Date updatedAt;

    @OneToMany(mappedBy = "product", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    private Set<ProductVariant> productVariants;

    @ManyToOne
    @JoinColumn(name = "subCategory_id")
    private SubCategory subCategory;
}

pom.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.0.5</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.eshop</groupId>
    <artifactId>eshop</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>eshop</name>
    <description>eshop</description>
    <properties>
        <java.version>17</java.version>
        <version.lombok>1.18.26</version.lombok>
        <version.mapstruct>1.3.1.Final</version.mapstruct>
        <version.mapstruct-lombok>0.2.0</version.mapstruct-lombok>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.0.4</version>
        </dependency>
        <dependency>
            <groupId>org.openapitools</groupId>
            <artifactId>openapi-generator-maven-plugin</artifactId>
            <version>6.4.0</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>8.0.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-envers</artifactId>
            <version>6.1.7.Final</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${version.lombok}</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${version.mapstruct}</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok-mapstruct-binding</artifactId>
            <version>${version.mapstruct-lombok}</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>17</source>
                    <target>17</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${version.lombok}</version>
                        </path>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${version.mapstruct}</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok-mapstruct-binding</artifactId>
                            <version>${version.mapstruct-lombok}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

已尝试调整pom依赖顺序、降级Lombok和MapStruct版本,问题未解决。此前问题曾突然消失,添加DTO字段后复现。执行clean install可正常生成相关类,但运行应用时仍触发错误。

解决方案
  • 升级MapStruct版本:当前使用的MapStruct 1.3.1.Final不兼容Spring Boot 3和Java 17,将版本升级到1.5.5.Final(稳定兼容版本),保持lombok-mapstruct-binding版本为0.2.0即可。
  • 调整注解处理器顺序:在maven-compiler-plugin的annotationProcessorPaths中,确保lombok路径放在mapstruct-processor之前,保证Lombok先生成getter/setter,MapStruct能正确识别实体属性。
  • 检查IDE注解处理器配置:如果使用IntelliJ IDEA,开启「Enable annotation processing」,路径:Settings -> Build, Execution, Deployment -> Compiler -> Annotation Processors。
  • 清理缓存并强制构建:执行mvn clean install -U强制更新依赖,同时清理IDE缓存(File -> Invalidate Caches... -> Invalidate and Restart)。
  • 修正映射表达式:在ProductMapper的map(ProductVariant)方法中,显式指定完整参数路径,避免MapStruct解析歧义:
@Mappings({
        @Mapping(target = "name", source = "productVariant.product.name"),
        @Mapping(target = "description", source = "productVariant.product.description"),
        @Mapping(target = "productId", source = "productVariant.product.id"),
})
ProductGetDetailsResponse map(ProductVariant productVariant);

对于ProductVariant中与DTO字段名一致的属性(如id、imageUrl等),无需手动配置映射,MapStruct会自动匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 07:57:02