1

我正在使用 Spring 框架。我有两张表包裹和物品,关系是一个包裹有很多物品。表格设计类似于:

套餐

    @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 FETCH 而不是 JOIN

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

作为 JPQL

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

如何正确表达 jpql-join-fetch-with-where-clause-as-jpa-2-criteriaq

于 2016-11-16T11:30:36.733 回答
0

我认为问题出在 SQL 语法上,在JOIN.

INNER JOIN:当两个表中至少有一个匹配时返回所有行

LEFT JOIN:从左表返回所有行,从右表返回匹配的行

有时它被称为LEFT OUTER JOIN.

RIGHT JOIN:从右表返回所有行,从左表返回匹配的行

FULL JOIN:当其中一个表中存在匹配时返回所有行

当您使用JOIN时,默认情况下,至少对于 SQL Server 和 MySQL,它等效于INNER JOIN. 我认为您的底层 lib/jar 还将为您提供其他JOIN类型的类。

尝试指定INNER JOIN,或WHERE试一试。对我WHERE来说更清楚。

这个问题可能会有所帮助:

可空多对一的休眠默认连接

于 2016-11-16T08:04:01.163 回答