@ SQLResultSetMapping +连接多个实体的结果不同JPA

时间:2016-12-30 20:14:19

标签: mysql hibernate jpa nativequery sqlresultsetmapping

我正在运行带有JPA的NativeQuery,与在sql工具中运行查询相比,它提供了不同的结果。可能我错过了解s.th.在@SQLResultSetMapping的概念中。

---概述---

我将结果映射到两个实体,所以我希望收到一个实体对列表。这很有效。

当您查看下面的图片时,您将在sql工具中看到查询结果,其中..

  • .. RED BOX映射到一个实体
  • .. GREEN BOX映射到第二个实体

JPA应该给我一个本机行作为一对两个实体。

问题

这是出问题的地方。是的,我将收到两个实体对的列表,但与图片中的不同之处是" pp.id"不会遍历相应表格的所有行(在图片中#34; 5,6,7,...",来自JPA" 5,5,5,5,...&#34 ;)

列pp.id是一个连接列,我想在Joins + SQLResultSetMappings中我错过了解JPA中的内容。在我看来,区别在于JPA总是加入表格' propertyprofile' (更详细说明如下),与查询在sql中运行时不同。

我希望有人对我表示同情并帮助我。 :)

---详情---

查询

我基本上试图找出每个产品是否已经定义了一个'值' (table propertyvalue)用于预定义的'属性' (table propertyprofile)。

可能最相关的部分位于底部,其中" propertyprofile"加入了" propertyvalue"是左派。

select sg.ID as 'sg.id', sg.Name as 'sg.name', ppcount.totalppcount as 'sg.totalppcount', ppcount.totalppothercount as 'sg.totalppothercount',
p.ID as 'product.id', pp.id as 'pp.id', pp.Role as 'pp.role', pp.Name as 'pp.name',
(case when pv.id is null then '0' else '1' end) as 'hasPropertyValue', pv.ID as 'pv.id', pv.StringValue, pv.IntervallMin, pv.IntervallMax
from shoppingguide sg
join
(
    select sg.ID as 'sgid', count(*) as 'totalppcount', count(pp_other.ID) as 'totalppothercount' from propertyprofile pp_all
    left join propertyprofile pp_other on pp_other.id = pp_all.id AND pp_other.Role = '0'
    join shoppingguide sg on pp_all.ShoppingGuideID = sg.ID
    join shopifyshop ss on sg.ShopifyShopID = ss.ID
    where
    pp_all.ShoppingGuideID = sg.ID AND
    ss.Name = :shopName
    GROUP BY pp_all.ShoppingGuideID
) ppcount on ppcount.sgid = sg.id
join shopifyshop ss on sg.ShopifyShopID=ss.ID
join product p on p.ShopifyShopID = ss.ID
join propertyprofile pp on (pp.ShoppingGuideID = sg.id AND pp.Role = '0')
left join propertyvalue pv on (pv.ProductID=p.ID and pv.PropertyProfileID = pp.id)
where 
ss.Name = :shopName
order by sg.id asc, p.id asc, pp.id asc
;

涉及很多表,但这些是理解查询最重要的表:

  • 产品
  • propertyprofile - 所有产品都具有的功能(例如身高,价格)
  • propertyvalue - 特定功能的数据;涉及propertyprofile(例如5cm; $ 120)

SQLResultSetMapping

映射是在两个entite上完成的:ProductDataFillSummary_ShoppingGuideInformation,ProductDataFillSummary_ProductInformation。

@SqlResultSetMapping(
        name = "ProductDataFillSummaryMapping",
        entities = {
            @EntityResult (
                    entityClass = ProductDataFillSummary_ShoppingGuideInformation.class,
                    fields = {
                        @FieldResult(name = "shoppingGuideId", column = "sg.id"),
                        @FieldResult(name = "shoppingGuideName", column = "sg.name"),
                        @FieldResult(name = "numberOfTotalPropertyProfiles", column = "sg.totalppcount"),
                        @FieldResult(name = "numberOfTotalPropertyProfilesOther", column = "sg.totalppothercount")
                    }),
            @EntityResult(
                    entityClass = ProductDataFillSummary_ProductInformation.class,
                    fields = {
                        @FieldResult(name = "productID", column = "product.id"),
                        @FieldResult(name = "propertyProfileId", column = "pp.id"),
                        @FieldResult(name = "propertyProfileRole", column = "pp.role"),
                        @FieldResult(name = "propertyValueId", column = "pv.id"),
                        @FieldResult(name = "hasPropertyValue", column = "hasPropertyValue")
                        }
                    )
        })

1 个答案:

答案 0 :(得分:0)

分析

问题似乎是Hibernate没有..

  • ..处理每一行
  • ..每行映射到指定实体
  • ..将此行的映射实体放入List(在我的示例中为一对​​实体)

实际上,hibernate似乎匹配两个实体,它们应该基于主键属性进入List的相同条目,即......这样:

  • ..处理每一行
  • ..为每个行映射到各个实体(单独)
  • ..使用主键
  • 存储映射的实体
  • ..匹配进入List
  • 的相同条目的各个实体

在我的例子中,一对[ProductDataFillSummary_ShoppingGuideInformation,ProductDataFillSummary_ProductInformation]将被插入到列表中。何时产品数据填写_产品信息'如果是,Hibernate将尝试使用主键找到正确的实例(此处为&ProductsFillSummary_ProductInformation.productId')。由于ProductDataFillSummary_ProductInformation的多行具有相同的productId值,因此始终会获取第一个实例并将其用于List。

解决方案

使用考虑' ProductDataFillSummary_ProductInformation.productId'的复合键。和' .propertyProfileId',或..

如果无法使用组合密钥,请使用人工密钥(uuid):

concat(p.ID, '-', pp.ID) as 'uuid'