【问题标题】:hibernate native query complex constructor mappinghibernate原生查询复杂构造函数映射
【发布时间】:2018-04-14 18:55:20
【问题描述】:

Java、Spring Data JPA

我有 2 个实体:

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"),
                }
        ),
        ... 
        ???
    }
)

@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 自动化...(因为我的真实对象更复杂)

【问题讨论】:

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


    【解决方案1】:

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

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

    然后在您的源代码库中创建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 &lt;condition&gt; 适用于 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();
    

    【讨论】:

    • 感谢投影链接和想法!它看起来很有用,但我的关键问题是本地查询映射(我的实体没有直接关系,我不能使用 HQL)
    • @Elegant.Obj Hibernate 5.1+ 支持不相关实体之间的连接,因此您可以使用 HQL。
    猜你喜欢
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    • 1970-01-01
    • 2013-04-03
    • 1970-01-01
    • 1970-01-01
    • 2021-10-12
    • 1970-01-01
    相关资源
    最近更新 更多