【问题标题】:Select few among all the nested entities : SPRING JPA在所有嵌套实体中选择几个:SPRING JPA
【发布时间】:2025-12-04 07:55:01
【问题描述】:

我有一个像下面这样的场景。

假设EntityA 有三个嵌套实体EntityB, EntityC, EntityD。并且所有EntityB, EntityC, EntityD 内部都有几个嵌套实体。

但在选择EntityA 时,它会选择整个嵌套实体树。而我想获取特定的分支。可以说只有EntityA, EntityBEntityB 的所有子实体都将被提取,留下EntityCEntityD 然后我不知道该怎么做。由于 spring jpa 将所有嵌套对象都带回给我。

我正在使用以下集合映射。


 @Entity
 @Table(name = "customer_party_mapping")
 @Data
 public class CustomerPartyMappingEntity {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Integer id;
    
    @Column(name = "customer_id")
    private Integer custmerId;
    
    @Column(name = "orgtype_id")
    private Integer orgTypeId;
    
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL )
    @JoinColumn(name = "customer_party_mapping_id")
    @Fetch(value = FetchMode.SUBSELECT)
    private List<CustomerPartyBookingLocationEntity> customerPartyBookingLocation=new ArrayList<CustomerPartyBookingLocationEntity>();
    
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL )
    @JoinColumn(name = "customer_party_mapping_id")
    @Fetch(value = FetchMode.SUBSELECT)
    private List<CustomerPartyFieldMappingEntity> customerPartyFieldMappingEntity=new ArrayList<CustomerPartyFieldMappingEntity>();

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL )
    @JoinColumn(name = "customer_party_mapping_id",referencedColumnName="id")
    @Fetch(value = FetchMode.SUBSELECT)
    private List<CustomerPartyOtherDocumentEntity> otherDocumentsList=new 
    ArrayList<>();
    
    @OneToOne( cascade={ CascadeType.PERSIST, CascadeType.MERGE })
    @JoinColumn(name = "customer_name_screening_id", referencedColumnName="id") 
    private CustomerNameScreeningEntity customerNameScreeningEntity;
        
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL )
    @JoinColumn(name = "customer_party_mapping_id")
    @Fetch(value = FetchMode.SUBSELECT)
    private List<CustomerDocInfoTrackingEntity> customerDocInfoTrackingList=new 
    ArrayList<CustomerDocInfoTrackingEntity>();
}

我正在打电话


List<CustomerPartyMappingEntity> customerPartyMappingEntityList = customerPartyMappingRepository.findByCustmerId(customerid);

它获取所有嵌套映射的实体列表,而我只需要CustomerPartyMappingEntity 及其customerPartyFieldMappingEntity 嵌套对象列表。

我们将不胜感激。

【问题讨论】:

    标签: java spring jpa spring-data-jpa


    【解决方案1】:

    首先将FetchType.LAZY 用于嵌套实体。 然后,您可以使用@EntityGraph 按名称获取嵌套实体,并在存储库中使用其名称和. 获取嵌套实体。您可以在 attributePaths 中指定嵌套属性,例如

    @EntityGraph(attributePaths = {"customerPartyBookingLocation"})
    

    customerPartyBookingLocation的嵌套属性一样

    @EntityGraph(attributePaths = {"customerPartyFieldMappingEntity.subField"})
    

    例子:

    @EntityGraph(attributePaths = {"customerPartyBookingLocation", "customerPartyFieldMappingEntity.subField"})
    List<CustomerPartyMappingEntity> findByCustmerId(Integer customerid);
    

    注意:您不能将@EntityGraph 与@Query 注释一起使用

    【讨论】:

    • 好的。然后,如果我想要检索嵌套集合的不同组合,那么我必须在存储库中有多个类似的方法吗?如果是这样,那么我不能对根实体使用派生查询,而必须使用@Query 方式.. 对吗?
    • @EntityGraph不能和@Query一起使用,可以用方法命名查询和@EntityGraph一起使用
    • 我不确定您所说的“方法命名查询”是什么意思。你是说 NamedEntityGraph 吗?
    • 不,其实我的意思是Query creation from method names
    • 我认为“从方法名称创建查询”和派生查询之间没有太大区别。它们在以下用例中都没有用。假设我仍然想在五种不同的情况下调用List&lt;CustomerPartyMappingEntity&gt; findByCustmerId(Integer customerid);,在这五种不同的情况下,每一种都需要一个不同的嵌套列表,而不是一次全部。所以我认为我应该使用 NamedEntityGraph 来实现这一点。无论如何感谢您的回复。
    【解决方案2】:

    如果您的实体确实设置正确,请参阅子选择示例 here 并删除您的 EAGER(您当前正在指示 hibernate 在实体初始化时获取所有这些字段)。它应该可以工作。

    【讨论】: