Hibernate——Hql实例+详解

    Hibernate配备了一种非常强大的查询语言,这种语言看上去很像SQL。完整的HQL语句形式如下:Select/update/delete…… from …… where …… group by …… having …… order by …… asc/desc。同时需要注意的是在hql中关键字不区分大小写,通常小写,类的名称和属性名称必须区分大小写,按照实体的设计去写大小写。

    下面从实例入手去进一步说明HQL的语音的用法。


搭建测试环境:

    测试中建立一个Classes实体类里面包含属性:id、班级名称、以及学生。student实体类里面包含:id、姓名、创建时间以及班级。student与classes是多对一的关系。

实体类

public class Student {
	private int id;
	private String name;
	private Date createTime;
	private Classes classes;
	public Date getCreateTime() {
		return createTime;
	}
	
	public Student() {
	}
	
	public Student(int id, String name) {
		this.id = id;
		this.name = name;
	}
	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}
	
	public Classes getClasses() {
		return classes;
	}
	public void setClasses(Classes classes) {
		this.classes = classes;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

public class Classes {
	private int id;
	private String name;
	
	private Set students;
	
	public Set getStudents() {
		return students;
	}
	public void setStudents(Set students) {
		this.students = students;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

映射文件:

<hibernate-mapping>
	<class name="com.syq.hibernate.Classes" table="t_classes">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<set name="students" inverse="true">
			<key column="classid"/>
			<one-to-many class="com.syq.hibernate.Student"/>
		</set>
	</class>
</hibernate-mapping>

<hibernate-mapping>
	<class name="com.syq.hibernate.Student" table="t_student">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<property name="createTime"></property>
		<many-to-one name="classes" column="classid"></many-to-one>
	</class>
</hibernate-mapping>

1.简单属性查询

单一属性查询,返会属性结果集列表,元素类型和实体类中相应的类型一致

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


多个属性查询,多个属性查询返会对象数组,对象数组的长度取决于属性的个数,对象数组中元素的类型取决于属性在实体类中的类型

List students=session.createQuery("select id,name from Student").list();


多个属性查询,也可以使用hql动态实例化Student对象,返回实体对象。

List students=session.createQuery("select new Student(id,name) from Student").list();


2、实体对象查询

N + 1问题

    就是发出了N+1条sql语句。1:首先发出查询对象id列表的语句。N:根据id到缓存中查询,如果缓存中不存在与之匹配的数据,那么会根据id发出相应的sql语句

    利用Iterator会出现N+1条SQL语句

Iterator iterator=session.createQuery("from Student").iterate();


    如果先使用List将数据查询到session中再使用Iterator进行查询,就不会产生N+1条SQL语句,原因是:list: 默认情况下list每次都会发出sql语句,list会将数据放到缓存中,而不利用缓存;iterate:默认情况下iterate利用缓存,如果缓存中不存在会出现N+1问题

List students=session.createQuery("from Student").list();
			for (Iterator iterator = students.iterator(); iterator.hasNext();) {
				Student student = (Student) iterator.next();
				System.out.println(student.getName());
			}
			System.out.println("---------------------------------------------");
			Iterator iterator=session.createQuery("from Student").iterate();
			while(iterator.hasNext()){
				Student student=(Student)iterator.next();
				System.out.println(student.getName());
			}


3、条件查询

采用拼字符串的方式传递参数

List students = session.createQuery("select s.id, s.name from Student s where s.name like '%0%'").list();


采用 “?”来传递参数(索引从0开始)

List students=session.createQuery("select s.id, s.name from Student s where s.name like ?")
			.setParameter(0, "%0%")
			.list();


采用 “:参数名” 来传递参数

List students=session.createQuery("select s.id, s.name from Student s where s.name like :myname")
			.setParameter(":myname", "%0%")
			.list();


传递多个参数采用setParamterList方法

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

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


hql中使用数据库的函数,如:date_format进行查询

List students=session.createQuery("select s.id, s.name from Student s where s.date_format(s.createTime,'%Y-%m')=? ")
			.setParameter(0, "2009-08")
			.list();

 

4、hibernate直接使用sql语句查询     

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


5、外置命名查询

    所谓的外置命名查询,就是将需要查询的sql语句以及条件写到映射文件中。

 1.在映射文件中使用<query>标签来定义hql

<query name="queryStudent">
<span style="white-space:pre">	</span><![CDATA[
	    select s from Student s where s.id<?
	 ]]>
</query>


 2.在程序中使用session.getNamedQuery()方法得到hql查询串

List students=session.getNamedQuery("queryStudent")
					.setParameter(0, 10)
					.list();</span>


6、过滤器查询

    过滤器查询在映射文件利用filter-def去定义一个过滤器,在过滤期中定义过滤器写条件。并在程序中为过滤器赋值。

 1.在映射文件中定义过滤器参数,在类的映射中使用过滤器参数

<class name="com.syq.hibernate.Student"table="t_student">
         <id name="id">
              <generator class="native"/>
         </id>
         <property name="name"/>
         <property name="createTime"></property>
         <many-to-one name="classes"column="classid"></many-to-one>
         <filter name="testFilter"condition="id < :myid"></filter>
     </class>
     <filter-def name="testFilter">
         <filter-param name="myid"type="integer"/>
     </filter-def>

 2.在程序中必须显示的启用过滤器,并且为过滤器参数赋值

//启动过滤器,并给过滤器添加条件
session.enableFilter("testFilter").setParameter("myid", 10);
List students=session.createQuery("from Student").list();


7、分页查询

setFirstResult(),从0开始,setMaxResults(),每页显示的记录数

List students=session.createQuery("from Student")
					.setFirstResult(1)
					.setMaxResults(2)
					.list();


8、对象导航查询

List students=session.createQuery("from Student s where s.classes.name like " +
					"'%2%'").list();

9、连接查询

内连接

List students=session.createQuery("select s.name,c.name from Student s join s.classes c").list();


左连接

List students=session.createQuery("select s.name,c.name from Student s left join s.classes c").list();


右连接

 List students=session.createQuery("select s.name,c.name from Student s right join s.classes c").list();


10、统计查询

count

List list=session.createQuery("select Count(*) from Student").list();
    或者直接返回统计数字
Long count=(Long)session.createQuery("select Count(*) from Student").uniqueResult();

group分组

String hql="select c.name,count(s) from Classes c join c.students s group by c.name" ;
List students=session.createQuery(hql).list();

    

    总之,可以利用hql进行灵活查询:进行条件查询、直接使用原生sql查询、外置名称查询、过滤器查询、分页查询、导航属性查询、连接查询、统计查询。但是所有的查询大多数都返回的是数组对象。只有使用“from student”语句、单一属性查询以及l动态实例化实体类对象的时候才能返回实体集合。


参考:王勇老师的《SSH视频》


评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值