【问题标题】:JPA-2.0 Simple Select-Where questionJPA-2.0 简单的 Select-Where 问题
【发布时间】:2011-04-05 20:55:33
【问题描述】:

我遇到了一个关于 JPA-2.0 查询与关系的问题。怎么可能选择任何Dataset 和至少一个Eventtype = B

@Entity
class Dataset {
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "dataset")
    public List<Event> events;
}

@Entity
class Event {
    @ManyToOne
    @JoinColumn
    public Dataset dataset;

    public Type type;
}

enum Type {
     A, B, C
}

我的出发点是

CriteriaBuilder _builder = em.getCriteriaBuilder();
CriteriaQuery<Dataset> _criteria = _builder.createQuery(Dataset.class);

// select from
Root<Dataset> _root = _criteria.from(Dataset.class);
_criteria.select(_root);

// apply some filter as where-clause (visitor)
getFilter().apply(
   _root, _criteria, _builder, em.getMetamodel()
);

// how to add a clause as defined before?
...

对此有任何想法。我尝试创建子查询和连接,但不知何故我做错了,结果总是得到所有数据集。

【问题讨论】:

    标签: java hibernate orm jpa-2.0 criteria-api


    【解决方案1】:

    试试

    SELECT d FROM DataSet d WHERE EXISTS 
        (SELECT e FROM Event e WHERE e.dataSet = d and e.type = :type)
    

    编辑:正如 Pascal 指出的那样,您似乎正在使用 Criteria API。不太熟悉这个,但我会刺伤。

    CriteriaBuilder builder = em.getCriteriaBuilder();
    CriteriaQuery<Dataset> criteria = builder.createQuery(Dataset.class);
    
    Root<Dataset> root = criteria.from(Dataset.class);
    criteria.select(root);
    
    // build the subquery
    SubQuery<Event> subQuery = criteria.subQuery(Event.class);
    Root<Event> eventRoot = subQuery.from(Event.class);
    subQuery.select(eventRoot);
    
    ParameterExpression<String> typeParameter = builder.parameter(String.class);
    Predicate typePredicate = builder.equal(eventRoot.get(Event_.type), typeParameter));
    
    // i have not tried this before but I assume this will correlate the subquery with the parent root entity
    Predicate correlatePredicate = builder.equal(eventRoot.get(Event_.dataSet), root);
    subQuery.where(builder.and(typePredicate, correlatePredicate);
    
    criteria.where(builder.exists(subQuery)));
    
    List<DataSet> dataSets = em.createQuery(criteria).getResultList();
    

    唷,这是一项艰苦的工作。我现在要回到 Linq。

    【讨论】:

    • 看起来 OP 正在尝试在这里使用 Criteria API。
    • 谢谢,它对我有用。我也弄清楚了为什么我的方法失败了。我试图重用已经执行的查询并添加了另一个子句。 Hibernate 没有报错,而是生成了错误的别名(主查询和子查询有相同的别名,显然失败了)。
    • 您需要添加subquery.select(eventRoot); 并检查谓词correlatePredicate 处的括号。最后builder.not(builder.exists(subQuery)) 应该没有not。非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 2017-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-19
    • 2013-04-06
    • 1970-01-01
    • 2012-02-05
    相关资源
    最近更新 更多