Spring数据JPA-如何使用投影和/或命名查询返回嵌套映射的ID?

问题描述

我有这些实体-项目

 @Entity
 @Table(name="Item")
 public class Item 
 {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private Long id;
    
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="item_set_id")
    private ItemSet itemSet;
    
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="category_id")
    private Category category;

    @Column(name="category_name")
    private String categoryName;
    
    // 5 other fields which aren't required for the query
 }

Category-

@Entity
@Table(name="Category")
public class Category
{
    @Id
    @Column(name="id")
    private Long id;
    
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="parent_id")
    private Category parent_id;
    
    @Column(name="name")    
    private String name;
}

我需要运行此SQL查询

select id,category_id,category_name from Item where item_set_id = ?

我正在ItemRepository中使用此[1],但性能不佳。它正在检索ItemCategory中的所有字段(包括不需要的与Category的联接)。

[1]

@Query("SELECT i FROM Item i WHERE item_set_id = ?1")
List<Item> findByItemSet(Long itemSetId);

我正在尝试使用命名查询和投影来提高性能,但似乎无处可寻。我一直遇到-Validation Failed for query for method public abstract java.util.List findByItemSet(Long)。我试图创建一个DTO类和一个接口来做同样的事情,但仍然无法正常工作。

@Query("SELECT a.id,"
            + "a.category_name,a.category_id FROM Item a WHERE a.item_set_id = :itemSetId")
    List<Item> findByItemSet(Long itemSetId);

关于如何解决此问题的任何想法/建议?

编辑:我正在使用springboot 2.0.4-RELEASE,java 8和MS-sql Server 2012。

解决方法

您在HQL查询中错误地使用了列名,而应该使用属性名。

您可以访问关联的属性,这就是JPA / Hibernate的优势。使用

@Query("SELECT a.id,a.categoryName,a.category.id FROM Item a WHERE a.itemSet.id = :itemSetId")
List<Tuple> findByItemSet(Long itemSetId);

如果需要实体对象,还可以使用以下内容

@Query("FROM Item a LEFT JOIN FETCH a.category WHERE a.itemSet.id = :itemSetId")
List<Item> findByItemSet(Long itemSetId);

如果要使用自定义DTO,请使用:

@Query("SELECT new com.dto.ItemDTO(a.id,a.category.id) FROM Item a WHERE a.itemSet.id = :itemSetId")
List<ItemDTO> findByItemSet(@Param("itemSetId") Long itemSetId);