Hibernate查询

    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();

你可能感兴趣的:(Hibernate查询)