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

Spring Data中QueryDSL无法为嵌套嵌入对象生成Q类求助

QueryDSL未生成嵌入类AddressDetails的Q类问题解决

问题场景

定义了MongoDB集合及嵌入文档结构如下:

PersonDetails.java

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@Document(collection = "person_details")
public class PersonDetails {
    @MongoId(FieldType.OBJECT_ID)
    private String managerId;

    @QueryInit("addressDetails.*")
    private List<ContactDetails> contactDetails;
}

ContactDetails.java

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ContactDetails {
    private AddressDetails addressDetails;
    private StateDetails stateDetails;
}

AddressDetails.java

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AddressDetails {
    private String address;
    @Field(targetType = FieldType.STRING)
    private AddressTypeEnum addressType;
}

StateDetails.java

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@Document(collection = "statedetails")
public class StateDetails {
    @MongoId(FieldType.OBJECT_ID)
    private String stateId;
    private String stateName;
}

构建项目后,QueryDSL仅生成了QPersonDetails和QContactDetails,但未生成QAddressDetails,导致构建Predicate时无法访问AddressDetails的字段(QContactDetails中addressDetails是SimplePath<AddressDetails>类型,无法链式调用内部字段)。尝试修改@QueryInit注解参数为*.*也未解决问题,且不想给AddressDetails添加@Document注解。

问题原因

QueryDSL默认仅会为标注了@Document的实体类生成Q类,对于普通的嵌入类(如AddressDetails),如果没有明确标记为可嵌入的持久化类,QueryDSL不会为其生成对应的Q类,仅会将其处理为SimplePath类型,无法展开内部字段。@QueryInit注解的作用是初始化路径层级,但不会触发Q类的生成。

解决方案

1. 给AddressDetails添加@Embeddable注解

@Embeddable是用于标记嵌入类的注解,QueryDSL会识别该注解并为类生成对应的Q类:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
@Embeddable // 关键注解
public class AddressDetails {
    private String address;
    @Field(targetType = FieldType.STRING)
    private AddressTypeEnum addressType;
}

2. 调整@QueryInit配置确保路径初始化

可以选择以下两种方式之一:

  • 在PersonDetails的contactDetails字段上更新@QueryInit:
    @QueryInit("*.addressDetails.*")
    private List<ContactDetails> contactDetails;
    
  • 或者在ContactDetails的addressDetails字段上添加@QueryInit:
    @QueryInit("*")
    private AddressDetails addressDetails;
    

3. 重新构建项目

执行项目构建命令(如mvn clean compile或gradle build)后,QueryDSL会生成QAddressDetails,同时QContactDetails中的addressDetails会变为QAddressDetails类型的路径,此时即可正常链式调用AddressDetails的字段构建Predicate,例如:

QPersonDetails person = QPersonDetails.personDetails;
Predicate predicate = person.contactDetails.any().addressDetails.address.eq("某地址");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 06:05:28