我很好奇为什么使用JPA 2的CriteriaBuilder
类可以创建这样的查询。假设我有一个User
类,其中持久String
为name
属性。我为什么要写这个?
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这样的其他查询框架会为这个问题提供更好的解决方案吗?
答案 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 Query或Torpedo Query(但这是专门针对HQL的),不需要编译时模型生成。无论如何QueryDsl是最早实现类型安全查询的人之一