使用Criteria或HQL的优点和缺点是什么?Criteria API是一种在Hibernate中表达查询的面向对象的好方法,但有时Criteria queries比HQL更难理解/构建。
什么时候使用标准,什么时候使用HQL?在哪些用例中您更喜欢什么?还是说这只是个人口味的问题?
使用Criteria或HQL的优点和缺点是什么?Criteria API是一种在Hibernate中表达查询的面向对象的好方法,但有时Criteria queries比HQL更难理解/构建。
什么时候使用标准,什么时候使用HQL?在哪些用例中您更喜欢什么?还是说这只是个人口味的问题?
当前回答
HQL可能会导致SQL注入等安全问题。
其他回答
另一点是,我认为Criteria更适合在它的基础上构建,而不是在最终代码中直接使用。
它更适合使用它来构建库,而不是使用jpql或hql。
例如,我使用Criteria API构建了spring-data-jpa-mongodb-expressions(与spring数据QBE的方式相同)。
我认为spring数据查询代使用jpaql而不是标准,我不明白为什么。
为了两全其美,HQL的表达性和简洁性以及Criteria的动态特性可以考虑使用Querydsl。
Querydsl支持JPA/Hibernate, JDO, SQL和Collections。
我是Querydsl的维护者,所以这个答案是有偏见的。
当我不知道哪些输入将用于哪些数据时,我通常使用Criteria。就像在一个搜索表单上,用户可以输入1到50个项目中的任何一个,我不知道他们会搜索什么。在检查用户正在搜索的内容时,很容易将更多内容添加到条件中。我认为在这种情况下放置HQL查询会更麻烦一些。当我确切地知道我想要什么时,HQL是很棒的。
标准API
Criteria API更适合动态生成查询。因此,如果您想添加WHERE子句过滤器、JOIN子句,或者改变ORDER BY子句或投影列,Criteria API可以帮助您以一种防止SQL注入攻击的方式动态生成查询。
另一方面,Criteria查询表达能力较差,甚至可能导致非常复杂和低效的SQL查询。
JPQL和HQL
JPQL是JPA标准实体查询语言,而HQL扩展了JPQL并添加了一些特定于hibernate的特性。
JPQL和HQL非常具有表现力,并且类似于SQL。与Criteria API不同,JPQL和HQL可以很容易地预测JPA提供者生成的底层SQL查询。复查HQL查询也比Criteria查询容易得多。
值得注意的是,如果需要修改实体,选择使用JPQL或Criteria API的实体是有意义的。否则,DTO投影是更好的选择。
结论
如果不需要改变实体查询结构,则使用JPQL或HQL。如果需要更改过滤或排序标准或更改投影,则使用criteria API。
然而,仅仅因为您正在使用JPA或Hibernate,这并不意味着您不应该使用本机SQL。SQL查询非常有用,JPQL和Criteria API不是SQL的替代品。
We used mainly Criteria in our application in the beginning but after it was replaced with HQL due to the performance issues. Mainly we are using very complex queries with several joins which leads to multiple queries in Criteria but is very optimized in HQL. The case is that we use just several propeties on specific object and not complete objects. With Criteria the problem was also string concatenation. Let say if you need to display name and surname of the user in HQL it is quite easy (name || ' ' || surname) but in Crteria this is not possible. To overcome this we used ResultTransormers, where there were methods where such concatenation was implemented for needed result. Today we mainly use HQL like this:
String hql = "select " +
"c.uuid as uuid," +
"c.name as name," +
"c.objective as objective," +
"c.startDate as startDate," +
"c.endDate as endDate," +
"c.description as description," +
"s.status as status," +
"t.type as type " +
"from " + Campaign.class.getName() + " c " +
"left join c.type t " +
"left join c.status s";
Query query = hibernateTemplate.getSessionFactory().getCurrentSession().getSession(EntityMode.MAP).createQuery(hql);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return query.list();
因此,在本例中,返回的记录是所需属性的映射。