在JPA中,为什么CriteriaBuilder让我在不相关的类型之间构建不健全的谓词?

时间:2012-10-19 19:30:33

标签: jpa-2.0 eclipselink hibernate-criteria querydsl

我很好奇为什么使用JPA 2的CriteriaBuilder类可以创建这样的查询。假设我有一个User类,其中持久Stringname属性。我为什么要写这个?

CriteriaBuilder builder = mgr.getCriteriaBuilder();

CriteriaQuery<User> crit = builder.createQuery(User.class);
Root<User> user = crit.from(User.class);                     // 1
crit.select(user)
    .where(builder.equal(user.get(User_.name), 2.5));        // 2

首先,在Marker 1:为什么我必须再次指出User.class?不是我的CriteriaQuery应该知道我对用户感兴趣吗?它是否打破了类型安全,可能会在这里注入另一个类?

其次,在Marker 2:name属性是String。为什么我可以这样编译废话,将String与双重进行比较?换句话说,为什么被调用的equal方法的签名是这样的:

public Predicate equal(Expression<?> x, Object y)

而不是大概更安全的版本如下?

public <T> Predicate equal(Expression<T> x, T y)

Querydsl这样的其他查询框架会为这个问题提供更好的解决方案吗?

2 个答案:

答案 0 :(得分:2)

我认为JPA 2 Criteria API的类型安全方面是在规范过程的最后阶段添加的。这就是为什么它感觉不一致。

Querydsl比JPA 2 Criteria API更简洁,也更安全。 Querydsl使用流畅的构造函数而不是工厂类来创建谓词,因此可以在此处找到等效方法http://www.querydsl.com/static/querydsl/2.8.0/apidocs/com/mysema/query/types/expr/SimpleExpression.html#eq%28T%29

我是Querydsl的维护者,所以这个答案有偏见。

答案 1 :(得分:2)

特定于JPA,你也可以使用Object QueryTorpedo Query(但这是专门针对HQL的),不需要编译时模型生成。无论如何QueryDsl是最早实现类型安全查询的人之一