繁体   English   中英

单向一对多关系的条件查询

[英]Criteria query for unidirectional one-to-many relationship

因此,我有以下实体:

@Entity
public class Supplier {
    @Column(name = "SUPPLIERID")
    private BigInteger supplierId;

    @OneToMany
    @JoinColumn(name = "ID_SUPP", foreignKey = @ForeignKey(name = "fk_POIS_SUPP"))
    private List<POS> posList;

    ...
}

@Entity
public class POS {
    @Column(name = "POSID")
    private BigInteger posId
}

因此, POS没有对Supplier的引用,这意味着我们具有单向一对多关系。 我需要寻找一个POS通过posIdsupplierId 即,找到具有指定的vendorId的供应supplierId ,然后在具有指定posId的pos的供应商列表中找到一个pos。 如何为此编写条件查询?

我尝试使用子查询。 我的想法是创建一个子查询可以取所有POS上的Supplier给定的supplierId 然后,主查询将在那些POS搜索具有给定posIdPOS

问题是我无法编写查询来获取SupplierPOS列表。 显然,您不能编写List<POS>类型的查询:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<POS> outerQuery = cb.createQuery(POS.class);
Root<POS> outerQueryRoot = outerQuery.from(POS.class);

Subquery<POS> subquery = outerQuery.subquery(POS.class);
Root<Supplier> subqueryRoot = subquery.from(Supplier.class);
subquery.where(cb.equal(subqueryRoot.get(Supplier_.supplierId), supplierId));
subquery.select(subqueryRoot.get(Supplier_.posList);

在最后一行,我得到一个编译错误, Expression<POS> does not match Expression<List<POS>> 而且我无法更改子查询的类型,因为Java不允许通用类文字( List<POS>.class )。

有任何想法吗?

我终于找到了答案,只需使用两个roots

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<POS> cq = cb.createQuery(POS.class);

    Root<POS> posRoot = cq.from(POS.class);
    Root<Supplier> supplierRoot = cq.from(Supplier.class);

    cq.where(cb.and(
                    cb.equal(supplierRoot.get(Supplier_.suppliertId), supplierId),
                    cb.equal(posRoot.get(POS_.posId), posId)));
    cq.select(posRoot);

我发现没有子查询的非常简单的解决方案。 从Suppler开始,通过posList加入POS,然后“选择” POS。

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<POS> query = cb.createQuery(POS.class);

Root<Supplier> supplierRoot = query.from(Supplier.class);
ListJoin<Supplier, POS> posList = supplierRoot.joinList(Supplier_.posList);
query
    .select(posList)
    .where(
        cb.equal(supplierRoot.get(Supplier_.suppliertId), supplierId),
        cb.equal(posList.get(POS_.posId), posId)
    );

使用Hibernate 5.2.11,它通过N-> M表通过两个内部联接生成了很好的查询,这与手动编写的代码;-)非常相似。 接受的答案是我猜错了,因为它跳过了“ posList”关系。 它将选择与指定供应商无关的POS对象。

您可以使用子查询来执行此操作。 等同于jpql的SQL“从POS p中选择p,其中p.id所在(从Supplier s中选择sp.id加入s.posList sp,其中s.id =:supplierId)”

请参阅JPA2 Criteria-API:在...中选择...(从此处选择)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM