首页 文章

条件查询选择连接

提问于
浏览
0

我需要帮助来在Criteria Query中转换这个JPQL查询:

SELECT u.documentList FROM Unit u WHERE u.id = :id

这是我试过的:

CriteriaQuery<Document> query = builder.createQuery(Document.class);
Root<Unit> root = query.from(Unit.class);
Join<Unit, Document> join = root.join(Unit_.documentList);
query.select(join);
query.where(builder.equal(root.get(AbstractEntity_.id), entity.getId()));

在返回空列表的复杂SQL查询中执行此查询结果 .

IMO这应该工作,也许这是一个错误?

我使用EclipseLink 2.5.2作为JPA提供程序,使用MySQL 5.6作为db .

这里生成的SQL:

SELECT ... 
FROM UNIT t3 
    LEFT OUTER JOIN (DOCUMENT_RELATION t4 
    JOIN UNIT t0 ON (t0.ID = t4.CHILD_ID) 
    JOIN DELIVERABLE t1 ON (t1.ID = t0.ID) 
    JOIN DOCUMENT t2 ON (t2.ID = t0.ID)) ON (t4.PARENT_ID = t3.ID) 
WHERE (t3.ID = 58)

SELECT ... 
FROM DOCUMENT_RELATION t6, 
    DOCUMENT t5, 
    DELIVERABLE t4, 
    UNIT t3, 
    DOCUMENT t2, 
    DELIVERABLE t1, 
    UNIT t0 
WHERE (((t3.ID = 58) AND (((t5.ID = t3.ID) AND ((t4.ID = t3.ID) AND (t4.ID = t3.ID))) AND (t3.DTYPE = 'Document'))) AND ((((t5.ID = t3.ID) AND ((t4.ID = t3.ID) AND (t4.ID = t3.ID))) AND (t3.DTYPE = 'Document')) AND (((t6.PARENT_ID = t3.ID) AND (t0.ID = t6.CHILD_ID)) AND (((t2.ID = t0.ID) AND ((t1.ID = t0.ID) AND (t1.ID = t0.ID))) AND (t0.DTYPE = 'Document'))))) LIMIT 0, 10

这是映射:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Unit extends NamedEntity
{
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "DOCUMENT_RELATION", joinColumns = @JoinColumn(name = "PARENT_ID"), inverseJoinColumns = @JoinColumn(name = "CHILD_ID"))
    protected List<Document> documentList = new ArrayList<>();
}

这是类层次结构:

AbstractEntity (abstract @MappedSuperClass)
    NamedEntity (abstract @MappedSuperClass)
        Unit (abstract @Entity joined-inheritance)
            Deliverable (abstract @Entity)
                Document (concrete @Entity)

找到解决方案

CriteriaQuery<Document> query = builder.createQuery(Document.class);

Root<Unit> root = query.from(Unit.class);
root.alias("root");

Root<Document> relation = query.from(Document.class);
relation.alias("relation");

query.select(relation);

query.where
(
    builder.equal(root.get(AbstractEntity_.id), item.getId()),
    builder.isMember(relation, root.get(Unit_.actionList))
);

1 回答

  • 1

    JPA规范禁止您尝试实现的目标 . 单值路径表达式在select子句中有效,但 collection-valued path expressions are not valid . 参见规范的第4.8章 . 我引用Pro JPA书:

    以下查询是非法的:SELECT d.employees FROM Department d

    Criteria查询也是如此 . 为什么不只是查询 Unit 并调用 getDocumentList()

    编辑:您也可以尝试反转查询:

    SELECT d FROM Document d WHERE d.unit.id=:id
    

相关问题