【Hibernate步步为营】--hql查询之实体对象查询

上篇文章简单介绍了hql它作为Hibernate的查询语言,封装了基本上SQL的所有查询操作,HQL能够实现对数据库文件的增删改查,该篇文章着重讨论HQL实体对象的查询方法。

一、实体对象查询

实体对象查询是hql查询的基础,作为一种对象查询语言,在查询操作时和sql不同,查询字符串中的内容要使用类名和类的属性名来代替。这种查询方法相对简单,只要有SQL功底,使用hql是很简单的,但是有一些问题需要注意,就是查询获取数据不是目的,需要考虑的是如何编写出高效的查询语句,这才是讨论的重点。

1.1 N+1问题

1.1.1 什么是N+1问题

在刚听到这个名词时疑惑可能是有的,以前根本就没有听过N+1问题,那么它是指什么呢?N+1指的是一张表中有N条数据,那么在获取这N条数据时会产生N+1条sql命令,这种操作被称为N+1。这里的1指的是发出一条查询id列表的语句,N则指根据id发出N条sql语句,加载相关的对象。这种查询操作效率很低,往往产生在迭代器中,也就是说如果我们将查询结果直接转化为迭代器,这时候就会出现这种问题,如下代码:

public void testQuery(){
	Session session=null;

	try{
		session=HibernateUtils.getSession();
		session.beginTransaction();

		/**
		 * 会出现N+1问题,所谓的N+1值得是发出了N+1条sql语句
		 *
		 * 1:发出一条查询id列表的语句
		 *
		 * N:根据id发出N条sql语句,加载相关的对象
		 */
		Iterator iter=session.createQuery("from Student").iterate();

		while(iter.hasNext()){
			Student student=(Student)iter.next();
			System.out.println(student.getName());
		}
		session.getTransaction().commit();
	}catch(Exception e){
		e.printStackTrace();
		session.getTransaction().rollback();
	}finally{
		HibernateUtils.closeSession(session);
	}
}

上面的这段查询代码就会产生N+1问题,因为查询时返回的是一个迭代器,这样没产生一次就会发出一条sql语句,这主要取决于Iterator的这种查询机制,它是从缓存中查询数据,如果缓存中不存在该数据那么首先会将数据转换到内存中,所以这时候就会发出一条sql查询语句,所以在每次迭代时就会产生一条sql语句。这种写法其实是一种错误,可以使用其它方法优化解决。

1.1.2 避免N+1问题

出现了N+1的问题是因为Iterate使用不当的原因,当然可以使用其它的方法来避免这种N+1的问题,这里介绍一种List的方法。List和Iterate最大的区别是List将数据放到缓存中,但是不利用缓存,默认情况下list每次都会发出sql语句。可以在使用Iterate之前,使用list将数据保存到数据库中,这样Iterate访问数据时就可以从缓存中读取,避免了N+1问题的出现,代码如下:

public void testQuery(){
	Session session=null;

	try{
		session=HibernateUtils.getSession();
		session.beginTransaction();

		List students=session.createQuery("from Student").list();

		System.out.println("---------------------------------");
		/**
		 * 避免了N+1问题
		 *
		 * 因为执行list操作后会将数据放到session的缓存中(一级缓存),所以采用iterate的时候
		 * 首先会发出一条查询id列表的语句,再根据id到缓存中加载相应的数据,如果缓存中存在与之匹配的数据
		 * 则不再发出根据id查询的sql语句,直接使用缓存中的数据
		 *
		 * Iterate方法如果缓存中存在数据,它可以提高性能,否则出现N+1问题
		 */
		//可以使用as别名
		Iterator iter=session.createQuery("from Student").iterate();

		while(iter.hasNext()){
			Student student=(Student)iter.next();
			System.out.println(student.getName());
		}
		session.getTransaction().commit();
	}catch(Exception e){
		e.printStackTrace();
		session.getTransaction().rollback();
	}finally{
		HibernateUtils.closeSession(session);
	}
}

上例 避免了N+1问题,因为执行list操作后会将数据放到session的缓存中(一级缓存),所以采用iterate的时候首先会发出一条查询id列表的语句,再根据id到缓存中加载相应的数据,如果缓存中存在与之匹配的数据, 则不再发出根据id查询的sql语句,直接使用缓存中的数据。 Iterate方法如果缓存中存在数据,它可以提高性能,否则出现N+1问题。

1.2 对象导航查询

对象导航是指在一个对象中按照对象的属性导航获取到另一个对象的数据,这样做可以简化查询语句,优化查询方法。如果按照我们平常的想法可能会再重写编写另一个类的对象,来获取另一个对象的操作,和对象导航对比语句比较累赘。

@SuppressWarnings({ "unchecked", "rawtypes" })
public void testQuery1(){
	Session session=null;

	try{
		session=HibernateUtils.getSession();
		session.beginTransaction();

		//返回结果集属性列表,元素类型和实体类中的属性类型一致
		List students=session.createQuery("from Student s where s.classes.name like '%2%'").list();

		for(Iterator ite=students.iterator();ite.hasNext();){
			Student obj=(Student)ite.next();
			System.out.println(obj.getName());
		}

		session.getTransaction().commit();
	}catch(Exception e){
		e.printStackTrace();
		session.getTransaction().rollback();
	}finally{
		HibernateUtils.closeSession(session);
	}
}

上例中的查询语句就使用了对象导航的方法,查询语句是从Student对象中查询的信息,但是要比对的对象属性却是来自于Classes对象的name属性,这时候使用对象导航的查询方法就会明显提高查询效率,优化查询语句,如果换做普通的查询方法就可能会产生大量的连接语句,很复杂。

二、sql原生查询

原生查询值的是使用SQL语句来查询获取数据,而不是采用hql语句,它的使用方法其实很简单,同hql类似,只需要使用createSQLQuery方法查询即可,它其实类似于hql的createQuery方法,代码如下:

public void testQeury(){
	Session session=null;
	try{
		session=HibernateUtils.getSession();
		session.beginTransaction();

		List list=session.createSQLQuery("select * from t_student").list();

		for(Iterator ite=list.iterator();ite.hasNext();){
			Object[] obj=(Object[])ite.next();
			System.out.println(obj[0]+","+obj[1]);
		}

		session.getTransaction().commit();
	}catch(Exception e){
		e.printStackTrace();
		session.getTransaction().rollback();
	}finally{
		HibernateUtils.closeSession(session);
	}
}

上面的代码使用了createSQLQuery方法,方法内的查询字符串就是SQL语句,它实现了底层的字符串查询方法,不同的是HQL又做了一层包装,在Hibernate.cfg.xml中配置相应的方言选项即可完成映射。

结语

对象查询方法是HQL不同于SQL的地方,在使用时加以区分即可。该篇文章主要针对对象查询的问题及查询方法做了详细的讨论另外还添加了SQL原生态的查询方法的使用。下篇文章将会详细讨论HQL的连接查询及统计查询。

【Hibernate步步为营】--hql查询之实体对象查询,布布扣,bubuko.com

时间: 2024-12-28 12:25:43

【Hibernate步步为营】--hql查询之实体对象查询的相关文章

Git.Framework 框架随手记--ORM查询返回实体对象

使用ORM有一个优势,可以通过某种机制将数据库中的数据转化为自己想要的对象形式数据.本章记录一下如何使用Git.Framework返回实体对象 一. Git.Framework 中提供的方法 在Git.Framework中有七个方法可以返回实体对象,先简答的看看这里的方法描述 (1) T GetSingle(int id); (2) T GetSingle(object value); (3) T GetSingle(T entity); (4) V GetSingle<V>(T entity

工具函数1 查询字符串与对象相互转化

查询字符串与对象相互转化 查询字符串转对象 //查询字符串转对象 var queryStr = 'a=1&b=2' var toObj=queryStr=>{ let obj={}; queryStr.split('&').forEach(item=>{ let[key,val]=item.split('='); obj[key]=val }) return obj } console.log(toObj(queryStr)) //{a: "1", b: &

Hibernate之HQL介绍

Hibernate中提供了多种检索对象的方式,主要包括以下种类: 导航对象图检索方式:根据已经加载的对象导航到其他对象 OID检索方式:根据对象的OID来检索对象 HQL检索方式:使用面向对象的HQL查询语言 QBC检索方式:使用QBC(Query By Criteria)API来检索对象.这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口 本地SQL检索方式:使用本地数据库的SQL查询语句 本文主要介绍第三种方式,也就是HQL检索对象. HQL(Hibernate Quer

【HQL】hibernate查询语言hql

hibernate查询语言hql 在hql中关键字不区分大小写,通常小写,类的名称和属性名称必须区分大小写 1.简单属性查询[重要] * 单一属性查询,返会属性结果集列表,元素类型和实体类中相应的类型一致 * 多个属性查询,多个属性查询返会对象数组,对象数组的长度取决于属性的个数 对象数组中元素的类型取决于属性在实体类中的类型 * 如果认为返会数组不够对象化,可以使用hql动态实例化Student对象 参见:SimplePropertyQueryTest.java 2.实体对象查询[重要] *

027 hibernate查询语言(HQL)

概述:数据查询与检索是Hibernate中的一个亮点,相对其他ORM实现而言,Hibernate提供了灵活多样的查询机制. 标准化对象查询(Criteria Query):以对象的方式进行查询,将查询语句封闭为对象操作.优点:可主动性好,符合Java程序员的编码习惯.缺点:不够成熟,不支持投影(projection)或统计函数(aggregation) n   例:查询用户名以“J”开头的所有用户 Criteria c = session.createCreateria(User.class);

EBS OAF开发中实体对象和视图对象的属性设置器

(版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 源文: Home > Oracle Application Framework Documentation Set, Release 12.2 > Oracle Application Framework Developer's Guide > Chapter 5: Implementing Server-Side Features > Entity Object and Vi

ORM单表查询,跨表查询,分组查询

单表查询之下划线 models.Tb1.objects.filter(id__lt=10, id__gt=1) # 获取id大于1 且 小于10的值models.Tb1.objects.filter(id__in=[11, 22, 33]) # 获取id等于11.22.33的数据models.Tb1.objects.exclude(id__in=[11, 22, 33]) # not in models.Tb1.objects.filter(name__contains="ven")

【Hibernate步步为营】--hql查询小介

HQL 是指Hibernate Query Language,它是Hibernate的查询语言,拥有一套自己的查询机制,它的查询语句和SQL非常类似.在使用的时候可以非常快上手.HQL提供了基本上SQL全部的查询功能,可是在使用HQL查询时有非常多地方须要注意.该篇文章整理了HQL查询过程中须要注意的一些主要的语法问题,在使用HQL查询时希望避免这些问题. 一.Hibernate简单介绍 HQL採用的是标准化对象查询.它是以对象的方式进行查询.将查询语句封装为对象操作.长处:可读性好.复合jav

Hibernate(十一)HQL查询

HQL:Hibernate Query Language HQL有几个特点: 与SQL相似,SQL中的语法基本上都可以直接使用; SQL查询的是表和表中的列:HQL查询的是对象与对象中的属性; HQL的关键字不区分大小写,类名与属性名区分大小写; select可以省略. package test.hibernate.hbmHQL; import java.util.HashSet; import java.util.Set; public class Department { private I