0

JPA を使用して NativeQuery を実行していますが、SQL ツールでクエリを実行する場合とは異なる結果が得られます。おそらく私はs.thを誤解しています。@SQLResultSetMapping の概念内。

- - 概要 - -

結果を 2 つのエンティティにマッピングしているので、エンティティ ペアのリストを受け取ることを期待しています。これは機能します。

下の図を見ると、クエリの結果が SQL ツールに表示されます。

  • .. RED BOX は 1 つのエンティティにマップされます
  • .. 緑のボックスは 2 番目のエンティティにマップされます

JPA は、ネイティブ行の 1 つを 2 つのエンティティのペアとして提供する必要があります。

問題

ここで問題が発生します。はい、両方のエンティティのペアのリストを受け取りますが、図とは異なり、列 "pp.id" はそれぞれのテーブルのすべての行を反復しません (図では "5,6,7,..", JPA「5,5,5,5,..」から)。

列 pp.id は結合された列です。結合 + SQLResultSetMappings に関しては、JPA 内で何かを誤解していると思います。違いは、クエリがSQLで実行される場合とは異なり、JPAが常にテーブル「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 - 特定の機能のデータ。プロパティプロファイルに関連する (例: 5cm; $120)

SQLResultSetMapping

マッピングは、ProductDataFillSummary_ShoppingGuideInformation、ProductDataFillSummary_ProductInformation の 2 つのエンティティに対して行われます。

@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")
                        }
                    )
        })
4

1 に答える 1

0

分析

問題は、休止状態がそうではないことです..

  • .. 各行を処理する
  • .. 指定されたエンティティへの行ごとのマップ
  • .. この行のマッピングされたエンティティを List に入れます (私の例ではエンティティのペア)

実際、休止状態は、主キー属性に基づいて、リストの同じエントリに入る必要がある両方のエンティティに一致するようです。つまり、次のような sth です。

  • .. 各行を処理する
  • .. 各行をそれぞれのエンティティに (個別に) マップする
  • .. 主キーを使用してマップされたエンティティを保存する
  • .. List の同じエントリに入るそれぞれのエンティティに一致

私の例では、[ProductDataFillSummary_ShoppingGuideInformation, ProductDataFillSummary_ProductInformation] のペアがリストに挿入されます。「ProductDataFillSummary_ProductInformation」が挿入されると、Hibernate は主キー (ここでは「ProductDataFillSummary_ProductInformation.productId」) を使用して正しいインスタンスを見つけようとします。ProductDataFillSummary_ProductInformation の複数の行が productId に同じ値を持つため、常に最初のインスタンスが取得され、List に使用されます。

解決

「ProductDataFillSummary_ProductInformation.productId」と「.propertyProfileId」を考慮した複合キーを使用するか、..

複合キーを使用できない場合は、人工キー (uuid) を使用します。

concat(p.ID, '-', pp.ID) as 'uuid'
于 2017-01-02T12:00:07.940 に答える