Hibernate查询语言hql,在hql中关键字不区分大小写,通常小写,类的名称和属性名称必须区分大小写。
1、简单属性查询
单一属性查询,返会属性结果集列表,元素类型和实体类中相应的类型一致。
//返回结果集属性列表,元素类型和实体类中的属性类型一致
List students = session.createQuery("select name from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
String name = (String)iter.next();
System.out.println(name);
}
多个属性查询,多个属性查询返会对象数组,对象数组的长度取决于属性的个数.对象数组中元素的类型取决于属性在实体类中的类型.
//查询多个属性,返回对象数组集合
//数组元素的类型与查询的属性类型一致
//数组的长度与select中查询的属性个数一致
List students = session.createQuery("select id, name from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
如果认为返会数组不够对象化,可以使用hql动态实例化Student对象
//可以使用hql返回Student对象
//需要提供构造函数,new Student(id, name)
List students = session.createQuery("select new Student(id, name) from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getId() + ", " + student.getName());
}
采用as命名别名
// 可以采用as命名别名
List students = session.createQuery("select s.id, s.name from Student as s").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
2、实体对象查询
//返回Student对象的集合
//可以忽select关键字
List students = session.createQuery("from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
//返回Student对象的集合
//可以忽select关键字,可以采用as命名别名
List students = session.createQuery("from Student as s").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
//返回Student对象的集合
//如果使用select查询实体对象,必须使用别名
//不支持select * from .....,这种语法
List students = session.createQuery("select s from Student as s").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
/**
* 采用list查询实体对象会发出一条查询语句,取得实体对象数据
*
* Hibernate: select student0_.id as id0_, student0_.name as name0_,
* student0_.createTime as createTime0_, student0_.classesid as classesid0_
* from t_student student0_
*/
List students = session.createQuery("from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
/**
* 会出现N+1问题,所谓的N+1指的是发出了N+1条sql语句
*
* 1:发出一条查询id列表的语句
* Hibernate: select student0_.id as col_0_0_ from t_student student0_
*
* N:根据id发出N条sql语句,加载相关的对象
* Hibernate: select student0_.id as id0_0_, student0_.name as name0_0_,
* student0_.createTime as createTime0_0_, student0_.classesid as classesid0_0_
* from t_student student0_ where student0_.id=?
*
*/
Iterator iter = session.createQuery("from Student").iterate();
while (iter.hasNext()) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
List students = session.createQuery("from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
/**
* 避免了N+1问题
* 因为执行list操作后会将数据放到session的缓存中(一级缓存),所以采用iterate的时候
* 首先会发出一条查询id列表的语句,再根据id到缓存中加载相应的数据,如果缓存中存在与之匹配的数据
* 则不再发出根据id查询的sql语句,直接使用缓存中的数据
* Iterate方法如果缓存中存在数据,它可以提高性能,否则出现N+1问题
*/
Iterator iter = session.createQuery("from Student").iterate();
while (iter.hasNext()) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
List students = session.createQuery("from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
/**
* 再此发出查询语句
* 在默认情况下,每次执行list查询实体对象都会发出查询语句,除非配置了查询缓存。
* 虽然一级缓存中存在Student数据,但list不用,所以仍然发出查询语句,
* 其实list就是只向缓存中放入数据,而不会利用缓存中的数据。
*/
students = session.createQuery("from Student").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println(student.getName());
}
list和iterate的区别:
list: 默认情况下list每次都会发出sql语句,list会将数据放到缓存中,而不会利用缓存。
iterate:默认情况下iterate利用缓存,如果缓存中不存在会出现N+1问题,如果缓存中存在就直接拿缓存数据。
3、条件查询
可以采用拼字符串的方式传递参数
//可以拼串
List students = session.createQuery("select s.id, s.name from Student s where s.name like '%李%'").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
可以采用 ?来传递参数(索引从0开始)
List students = session.createQuery("select s.id, s.name from Student s where s.name like ?")
.setParameter(0, "%李%").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
可以采用 :参数名 来传递参数
//可以采用 :参数名 的方式传递参数
List students = session.createQuery("select s.id, s.name from Student s where s.name like :myname")
.setParameter("myname", "%李%").list();
for (Iterator iter=students.iterator(); iter.hasNext();) {
Object[] obj = (Object[])iter.next();
System.out.println(obj[0] + ", " + obj[1]);
}
如果传递多个参数,也可以采用setParamterList方法
//采用 ?方式,查询学号为1,2,3,4,5的学生
List students = session.createQuery("select s.id, s.name from Student s where s.id in(?, ?, ?, ?, ?)")
.setParameter(0, 1)
.setParameter(1, 2)
.setParameter(2, 3)
.setParameter(3, 4)
.setParameter(4, 5)
.list();
// setParamterList
List students = session.createQuery("select s.id, s.name from Student s where s.id in(:ids)")
.setParameterList("ids", new Object[]{1, 2, 3, 4, 5})
.list();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//查询2009-08-01 到2009-08-20的学生,可以调用mysql的日期格式化函数
List students = session.createQuery("select s.id, s.name from Student s where s.createTime between ? and ?")
.setParameter(0, sdf.parse("2009-08-01 00:00:00"))
.setParameter(1, sdf.parse("2009-08-20 23:59:59"))
.list();
4、hibernate直接使用sql语句查询
List students = session.createSQLQuery("select * from t_stu")
.addEntity(Student.class).list();
for (Iterator iter = students.iterator(); iter.hasNext();) {
Student obj = (Student) iter.next();
System.out.println(obj.getId() + ", " + obj.getName());
}
5、外置命名查询
在映射文件中使用<query>标签来定义hql
<query name="queryStudent">
<![CDATA[
select s from Student s where s.id <?
]]>
</query>
在程序中使用session.getNamedQuery()方法得到hql查询串
List students = session.getNamedQuery("queryStudent")
.setParameter(0, 10). list();
6、查询过滤器
在映射文件中定义过滤器参数
<hibernate-mapping>
<class name="com.zero.vo.Student" table="t_student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<filter name="testFilter" condition="id < :myid"></filter>
</class>
<filter-def name="testFilter">
<filter-param type="integer" name="myid"/>
</filter-def>
</hibernate-mapping>
在程序中必须显示的启用过滤器,并且为过滤器参数赋值
session.enableFilter("testFilter").setParameter("myid", 10);
List students = session.createQuery("from Student").list();
7、分页查询
setFirstResult(),从0开始
setMaxResults(),每页显示的记录数
List students = session.createQuery("from Student")
.setFirstResult(0)
.setMaxResults(10)
.list();
8、对象导航查询
List students = session.createQuery("from Student s where s.classes.name like '%3%'")
.list();
9、连接查询
List students = session.createQuery("select c.name, s.name from Student s join s.classes c").list();
List students = session.createQuery("select c.name, s.name from Student s left join s.classes c").list();
List students = session.createQuery("select c.name, s.name from Student s right join s.classes c").list();
10、统计查询
Long count = (Long)session.createQuery("select count(*) from Student").uniqueResult();
String hql = "select c.name, count(s) from Classes c join c.students s group by c.name order by c.name";
List students = session.createQuery(hql).list();