主要由三种查询:HQL查询、Criteria条件查询、SQL查询。
以下分别讲解
1. HQL查询
HQL(Hibernate Query Language)查询提供了更加丰富和灵活的查询特性,因此Hibernate将HQL查询立为官方推荐的标准查询方式。
HQL语法与SQL相似,但HQL是一种面向对象的查询语言,操作的是类、实例和属性等。
HQL是完全面向对象的查询语言,支持继承和多态等特性。
HQL查询步骤
(1) 获得Hibernate Session对象
(2) 设计HQL查询语句
(3) 以HQL查询语句作为参数,调用Session.createQuery(hql)方法创建查询对象
(4) 如果HQL查询语句包含参数,调用Query的setXxxx()方法为参数赋值
(5) 调用Query对象的list等方法遍历查询结果
public class HqlQueryTest{ private void findStudents(){ SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); Session session = sessionFactory.openSession(); Transaction trans = session.beginTransaction(); Query query = session.createQuery("FROM Student as stu WHERE stu.studentid=:sid"); query.setString("sid", "123456"); List list = query.list();for... trans.commit(); session.close(); sessionFactory.close(); } }
Query接口提供了绑定各种Hibernate映射类型的方法,
如:setBinary()/setString()/setBoolean()/setByte()/setCalendar()/setCharacter()/setDate()/setDouble()/setText()/setTime()/setTimestamp()。
还包含了两个用于实现Hibernate分页的方法:
① setFirstResult(int firstResult):设置返回的结果集从第几条记录开始;
② setMaxResults(int maxResults):设置本次查询返回的结果数;
HQL语法分析
HQL语句本身不区分大小写,但HQL中使用的包名、类型、实例名及属性名都区分大小写。
(1) FROM子句
from Student as st
该子句返回Student持久化类的所有实例,通常推荐起别名;
(2) SELECT子句
select子句选择将哪些对象与属性返回到查询结果集中,当然选择的属性必须是from后持久化类包含的属性。如:
SELECT st.name FROM Student as st
select可以选择任意属性,不仅可以选择持久化类的直接属性,还可以选择引用属性包含的属性(关联内容)。如:
SELECT st.class FROM Student as st
(3) 聚集函数
HQL查询甚至可以返回作用与属性之上的聚集函数的计算结果,HQL支持的聚集函数与SQL完全相同。有5种:
① avg:计算属性平均值;
② count:统计选择对象的数量;
③ max:统计属性值的最大值;
④ min:统计属性值的最小值;
⑤ sum:计算属性值的总和;
如:
SELECT count(*) FROM Student
SELECT max(st.age) FROM Student as st
(4) 多态查询
HQL语句被设计成能理解多态查询,Hibernate可以在from子句中指定任何Java类或接口,其from后跟的持久化类名不仅会查询出该持久化类的全部实力,还会查询出该类中子类的全部实例。
如:FROM Student as st    //该查询语句不仅会查询出Student的全部实例,还会查询出Student的子类
(5) WHERE子句
where子句用于筛选选中的结果,以缩小选择的范围。
如: FROM Student as st WHERE st.name LIKE “张%”
where子句中的属性表达式必须以基本类型或java.lang.String结尾,不要使用引用类型属性结尾。
如Student有class属性,class有classname属性:
FROM Student as st WHERE st.class.Classname LIKE “td%”  //正确
FROM Student as st WHERE st.class LIKE “td%”                   //不正确
(6) 表达式
HQL的表达式非常多,其where子句后支持的运算符也很多,不仅包括SQL的运算符,也包括EJB-QL的运算符等。
在where子句中允许使用的表达式包括大多数可以在SQL中使用的表达式。
· 数学运算符: + 、-、*、/  等
· 二进制比较运算符: =、<=、>=、<>、!=、like 等
· 逻辑运算符:and、or、not 等
· 判断字:in、not in、between、is null、is not null、is empty、is not empty、memberof、not memberof 等
· 条件判断:case、case…when…then…else…end 等
· 字符串连接符:value1 || value2或使用函数 concat(value1, value2)
· 时间操作函数:currentDate、currentTime、currentTimestamp、second、minute、hour、day、month、year 等
· HQL还支持EJB-QL3.0所支持的函数或操作substring、trim、lower、upper、Length、locate、abs、sqrt、bit_length和nullif 等
· 支持数据库的类型转换函数,如cast(…as….),第二个参数是Hibernate的类型名,或者extract(…from…),前提是底层数据库支持ANSI cast和extract
· 如果底层数据库支持单行函数sign、trunk、rtrim()、sin,则HQL语句也可以完全支持
· HQL语句支持使用“?”作为参数占位符,这与JDBC的参数占位符一致,也可以使用命名参数展位符号,方法是在参数名前加冒号“:”,如 :username、:xxx等
· 可在where子句中使用SQL常量,如“tfnew21”、66、”2009-04-21”等
· 还可以在HQL语句中使用Java public static final常量,如CC.Color.TABBY
在这些结构变量中:size、elements、ndices、minindex、maxindex、minelement、maxelement等只能在where子句中使用。
在where子句中,有序集合的元素(arrays、lists、maps)可以通过“[]”运算符访问。用法如下:
FROM Student as st where st.class[0].classname is not null
group by子句返回聚集值(Aggregate Values)的查询可以按照一个返回的类或组件(Components)中的任何属性(Property)进行分组,可以对持久化类或引用属性的属性进行分组,分组时可使用group by子句。如下:
SELECT st.age, count(st.name) FROM Student as st GROUP BY st.age
类似于SQL的规则,出现在select后的属性要么出现在聚集函数中,要么出现在group by的属性列表中。
having子句用于对分组进行过滤,having子句只能在有group by子句时才可以使用。如:
SELECT st.age, count(st.name) FROM Student as st GROUP BY st.age HAVING st.age BETWEEN 21 AND 25;
根据查询返回的列表(list),可以按照一个返回的类或组件中的任何属性用order by子句进行排序。
可以使用ASC(升序)、DESC(降序)指定排序规则,没有指定则默认采用升序规则。如:
FROM Student as st ORDER BY st.age DESC
group by和order by子句中都不能包含算数表达式。
对于集合属性,Hibernate默认采用延迟加载策略。
例如,对于持久化类Student,有集合属性class,加载Student实例时,默认不加载class属性。如果Session被关闭,则Student实例将无法访问关联的class属性。
为了解决该问题,可以在Hibernate映射文件中取消延迟加载,或者使用fetch jion。如:
FROM Student as st FETCH JOIN st.class    //此处的fetch语句将会初始化Student的class集合属性
如果使用了属性级别的延迟加载,可以用fetch all properties来强制Hibernate立即获取那些原本需要延迟加载的属性。如:
FROM Student FETCH ALL PROPERTIES WHERE age>12 ORDER BY age
HQL查询还支持查询所用的HQL语句放入配置文件中,而不是代码中。通过这种方式,可以大大提高程序设计的灵活度。如下:
<query name="getStudent”>
  FROM Student FETCH ALL PROPERTIES WHERE age>? ORDER BY age
</query>
在程序中调用命名查询的方法为:
Query query = session.getNamedQuery(“getStudent”);
query.setInteger(0, 21);
 
2. Creteria条件查询
条件查询是更具面向对象特色的数据查询方式,通过以下三个类完成:
· Creteria:代表一次查询
· Criterion:代表一个查询条件
· Restrictions:产生查询条件的工具类
执行条件查询的步骤:
(1) 获得Hibernate的Session对象
(2) 以Session对象创建Criteria对象
(3) 增加Criterion查询条件
(4) 执行Criteria的list等方法返回结果集
如:
//增加的限制条件必须是Student已经存在的属性
Criteria cri = session.createCriteria(Student.class);
cri.add(Restrictions.gt(“studentid”, new Integer(123)));
List list = cri.list();
在条件查询中,Criteria接口代表一次查询,该查询本身不具备任何的数据筛选功能。
调用createCriteria(Class class)方法对某个持久化类创建条件查询实例。
Criteria常用方法
Criteria add(Criterion criterion):增加查询条件;
Criteria addOrder(Order order):增加排序规则;
List list():返回结果集;
分页查询用的两个方法:
Criteria setFirstResult(int firstResult):设置查询返回的第一行记录;
Criteria setMaxResult(int maxResult):设置查询返回的记录数;
Criterion接口代表一个查询条件,该查询条件由Restrictions负责产生,而Restrictions是专门用于产生查询条件的工具类,它的方法大部分都是静态方法。
常用的方法有如下几种:
static Criterion allEq(Map propertyNameValues):判断指定属性(由Map参数的key指定)和指定值(由Map参数的value指定)是否完全相等;
static Criterion between(String propertyName, Object obj1, Object obj2):判断属性值是否在某个值范围之内;
static Criterion ilike(String propertyName, Object value):判断属性值是否匹配某个字符串;
static Criterion ilike(String propertyName, String value, MatchMode matchMode):判断属性值是否匹配某个字符串,并确定匹配模式;
static Criterion in(String propertyName, Collection values):判断属性值是否在某个集合内;
static Criterion in(String propertyName, Object[] values):判断属性值是否数组元素的其中之一;
static Criterion isEmpty(String propertyName):判断属性值是否为空;
static Criterion isNotEmpty(String propertyName):判断属性值是否不为空;
static Criterion isNull(String propertyName):判断属性值是否不为空;
static Criterion isNotNull(String propertyName):判断属性值是否不为空;
static Criterion not(Criterion expression):对Criterion求否;
static Criterion sizeEq(String propertyName, int size):判断某个属性的元素个数是否与size相等;
static Criterion sqlRestriction(String sql):直接使用SQL语句作为筛选条件;
static Criterion sqlRestriction(String sql, Object value, Type type):直接使用带参数占位符的SQL语句作为条件,并指定参数值;
static Criterion sqlRestriction(String sql, Object[] value, Type[] type):直接使用带参数占位符的SQL语句作为条件,并指定多个参数值;
如果需要使用关联类的属性来增加查询条件,则应该对属性再次使用createCriteria方法,用法如下:
session.cerateCriteria(Student.class)
  .add(Restriction.like(“name”, “天风”)).createCriteria(“classes”).add(Restriction.like(“className”, “班级名”)).list();
注意:查询并不是查询class持久化类,而是查询Student持久化类。
 
3. SQL查询
Hibernate还支持使用SQL查询,使用SQL查询可以利用某些数据库的特性,或者用于将原有的JDBC应用移植到Hibernate应用上。
SQL查询是通过SQLQuery接口来表示的,由于SQLQuery接口是Query接口的子接口,因此完全可以调用Query接口的方法。
执行SQL查询的步骤如下:
(1) 获取Hibernate Session对象;
(2) 编写SQL语句;
(3) 以SQL语句作为参数,调用Session的createSQLQuery方法创建查询对象;
(4) 如果SQL语句包含参数,则调用Query的setXxx方法为参数赋值;
(5) 调用SQLQuery对象的addEntity或addScale方法将选出的结果与实体关联;
(6) 调用Query的list方法返回查询的结果集
使用如下:
List list = session.createSQLQuery(“SELECT {st.*} FROM student as st ”).addEntity(“st”, Student.class).list();
如果不使用{st.*}形式,就可让实体别名与表别名互不相同,关联实体的类型时,被关联的类必须有对应的setter方法。