简体   繁体   English

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

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

So, I have the following entities: 因此,我有以下实体:

@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
}

So, POS does not have a reference to Supplier , which means that we have a unidirectional one-to-many relationship. 因此, POS没有对Supplier的引用,这意味着我们具有单向一对多关系。 I need to look for a POS by posId and supplierId . 我需要寻找一个POS通过posIdsupplierId That is, find a supplier with the specified supplierId and then find a pos in the supplier's list of pos's that has the specified posId. 即,找到具有指定的vendorId的供应supplierId ,然后在具有指定posId的pos的供应商列表中找到一个pos。 How do I write a criteria query for this? 如何为此编写条件查询?

I tried using subqueries. 我尝试使用子查询。 My idea was to create a subquery that would fetch all POS 's of a Supplier with a given supplierId . 我的想法是创建一个子查询可以取所有POS上的Supplier给定的supplierId Then the main query would search within those POS 's for a POS with the given posId . 然后,主查询将在那些POS搜索具有给定posIdPOS

The problem was I couldn't write a query that would fetch a Supplier s list of POS s. 问题是我无法编写查询来获取SupplierPOS列表。 Apparently you can't write a query of type List<POS> : 显然,您不能编写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);

On this last line, I get a compilation error that Expression<POS> does not match Expression<List<POS>> . 在最后一行,我得到一个编译错误, Expression<POS> does not match Expression<List<POS>> And I can't change the type of the subquery because Java doesn't allow generic class literals ( List<POS>.class ). 而且我无法更改子查询的类型,因为Java不允许通用类文字( List<POS>.class )。

Any ideas? 有任何想法吗?

I finally found the answer, just use two roots : 我终于找到了答案,只需使用两个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);

I found very simple solution without subquery. 我发现没有子查询的非常简单的解决方案。 Start from Suppler, join POS through posList and then 'select' POS. 从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)
    );

With Hibernate 5.2.11 it generated nice query with two inner joins through N->M table very similar to manually written code ;-). 使用Hibernate 5.2.11,它通过N-> M表通过两个内部联接生成了很好的查询,这与手动编写的代码;-)非常相似。 Accepted answer is I guess wrong because it skips "posList" relation. 接受的答案是我猜错了,因为它跳过了“ posList”关系。 It will select POS objects which are not in relation with specified Supplier. 它将选择与指定供应商无关的POS对象。

You can do this with subqueries. 您可以使用子查询来执行此操作。 SQL equivalent to the jpql "select p from POS p where p.id in (select sp.id from Supplier s join s.posList sp where s.id = :supplierId)" 等同于jpql的SQL“从POS p中选择p,其中p.id所在(从Supplier s中选择sp.id加入s.posList sp,其中s.id =:supplierId)”

See JPA2 Criteria-API: select... in (select from where) 请参阅JPA2 Criteria-API:在...中选择...(从此处选择)

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

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