1

Spring フレームワークを使用しています。パッケージとアイテムの 2 つのテーブルがあり、関係は 1 つのパッケージに多くのアイテムがあります。テーブルのデザインは次のようなものです。

パッケージ

    @Entity
    @Table(name = "TB_PACKAGE")
    public class Packages implements Serializable{

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    @Column(name = "PACKAGE_ID")
    private String packageId;

    @Valid
    @OneToMany(mappedBy = "packages", cascade = { CascadeType.ALL })
    private List<Item> item;

アイテム

    @Entity
    @Table(name = "TB_ITEM")
    public class Item implements Serializable{

    @Id
    @GeneratedValue(generator = "system-uuid")
    @GenericGenerator(name = "system-uuid", strategy = "uuid")
    @Column(name = "ITEM_ID")
    private String itemId;

    @ManyToOne
    @JoinColumn(name="PACKAGE_ID")
    private Packages packages;

    @Transient
    private String packageId;

サンプルレコード

これは、CriteriaBuilder を使用してテーブルを結合するコードを記述し、このような結果を得る方法です。

SQL:

    SELECT * FROM Packages p JOIN Item i ON p.packageId = i.packageId; 

ジャワ:

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<Packages> cq = cb.createQuery(Packages.class);
    Root<Packages> pRoot = cq.from(Packages.class);
    Join<Packages, Item> packagesItem = pRoot.join("item");
    List<Predicate> predicates = new ArrayList<Predicate>();

    if (StringUtils.isNotEmpty(itemName)) {
        predicates.add(cb.like(cb.lower(packagesItem.<String>get("itemName")), "%" + itemName.toLowerCase() + "%"));
    }

    Predicate[] predArray = new Predicate[predicates.size()];
    predicates.toArray(predArray);

    cq.where(predArray);
    cq.distinct(true);

    TypedQuery<Packages> query = em.createQuery(cq);

    return query.getResultList();

パラメータとして「電話」を入力すると、JSON としてレコードが出力されるはずです。

   "packageId": "P1",
   "item": [
        {
          "itemId": "Item 1",
          "temName" "Phone"
        }
    ]

ただし、パッケージは常に次のようにすべての子をロードします。

   "packageId": "P1",
   "item": [
        {
          "itemId": "Item 1",
          "temName" "Phone"
        },
        {
          "itemId": "Item 2",
          "temName" "Laptop"
        },
        {
          "itemId": "Item 3",
          "temName" "Mouse"
        }
    ]

FetchType.Lazy、QueryDsl、Native Query、HQL など、すべて試してみましたが、まだ運がありません。誰にも解決策がありますか?

4

3 に答える 3

0

あなたの@OneToManyマッピングは正しくないようです。変更してみる

@Valid
@OneToMany(mappedBy = "items", cascade = { CascadeType.ALL })
private List<Item> item;

@Valid
@OneToMany(mappedBy = "packages", cascade = { CascadeType.ALL })
private List<Item> item;

マッピングが完了したら、確認する必要がありますJOIN FETCH

于 2016-11-16T07:29:15.360 に答える
0

必要なのはJOINの代わりにJOIN FETCHです

Join<Packages, Item> packagesItem = pRoot.fetch("item");

JPQLとして

Select packages from Packages packages join fetch packages.item where packages.item.temName like '%'+itemName+'%';

how-to-properly-express-jpql-join-fetch-with-where-clause-as-jpa-2-criteriaq

于 2016-11-16T11:30:36.733 に答える
0

問題は SQL 構文にあると思いますJOIN

INNER JOIN: 両方のテーブルに少なくとも 1 つの一致がある場合、すべての行を返します。

LEFT JOIN: 左側のテーブルからすべての行を返し、右側のテーブルから一致した行を返します

と呼ばれることもありLEFT OUTER JOINます。

RIGHT JOIN: 右側のテーブルからすべての行を返し、左側のテーブルから一致した行を返します

FULL JOIN: テーブルの 1 つに一致がある場合、すべての行を返します

を使用する場合JOIN、デフォルトでは、少なくとも SQL Server と MySQL の場合は と同等INNER JOINです。JOIN基礎となる lib/jar は、他のタイプのクラスも提供すると思います。

を指定するか、試してみINNER JOINWHEREください。私にとってWHEREはより明確です。

この質問は役立つかもしれません:

null 許容多対 1 の Hibernate デフォルト結合

于 2016-11-16T08:04:01.163 に答える