hibernate本机查询复杂的构造函数映射

时间:2018-04-14 18:55:21

标签: java spring-data-jpa sqlresultsetmapping hibernate-native-query

Java,Spring Data JPA

我有两个实体:

class Source {
  Integer id;
  String name;
}

class Item {
  Integer id;
  String name;
  Integer sourceId;
} 

我需要这样的统计本机查询结果:

 select s.id source_id, s.name source_name, count(i.id) item_count
 from source s
 left join item i on s.id = i.source_id
 group by s.id 

我希望得到Java对象MyResult的结果:

class MyResult {
  Source source;
  Integer itemCount;
  MyResult(Source source, Integer itemCount) {...}
}

最接近的解决方案是使用@SqlResultSetMapping,如下所示:

@SqlResultSetMapping(
    name = "MyResultMapping",
    entities = {
        @EntityResult(
             entityClass = Source.class,
                fields = {
                    @FieldResult(name = "id", column = "source_id"),
                    @FieldResult(name = "name", column = "source_name"),
                }
        ),
        ... 
        ???
    }
)

OR

@SqlResultSetMapping(
    name = "MyResultMapping",
    classes = {
        @ConstructorResult(
            targetClass = MyResult.class,
                columns = {
                    @ColumnResult(name = "???"),
                    ???
                }
        )
    }
)

使用第二种变体,我可以使用类似的东西:

MyResult(Integer sourceId, String sourceName, Integer itemsCount) {
    this.source = new Source(sourceId, sourceName);
    this.itemsCount = itemsCount;
}

但是我想让它自动化@SqlResultSetMapping ...(因为我的真实对象更复杂)

1 个答案:

答案 0 :(得分:0)

使用Spring Data JPA,最好使用projections来满足您的需求,例如:

public interface SourceWithItemCount {
    Source getSource();
    Integer getItemCount();
}

然后在您的Source资源库中创建HQL查询方法,如下所示:

public interface SourceRepo extends JpaRepository<Source, Integer> {
    @Query("select s as source, count(i) like itemCount from Source s left join Item i on i.sourceId = s.id group by s"
    List<SourceWithItemCount> getSourcesWithItemCount();
}

重要提示是为返回值(s as source等)使用别名。它允许Spring Data JPA将它们映射到投影属性。

Join on <condition>适用于Hibernate版本5.1+(如果我没有弄错的话),所以我建议您在对象之间创建经典的one-to-many关系,例如:

@Entity
class Source {
    @Id private Integer id;
    private String name;
    @OneToMany @JoinColumn(name = "source_id") private List<Item> items;
}

@Entity
class Item {
    @Id private Integer id;
    private String name;
} 

然后创建所有版本的Hibernate(以及其他ORM提供程序)支持的JPQL查询方法:

@Query("select s as source, count(i) like itemCount from Source s left join s.items i group by s"
List<SourceWithItemCount> getSourcesWithItemCount();