HQL使用技术
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第三章HQL使用技术
1.Hibernate支持两种主要的查询方式:
HQL(Hibernate Query Language,Hibernate查询语言)查询和Criteria 查询。
1)HQL是一种面向对象的查询语言,其中没有表和字段的概念,只有类和属性的概念
2)Criteria查询又称为“对象查询”,它用面向对象的方式将构造查询的过程做了封装。
2.使用HQL可以避免使用JDBC查询的一些弊端
1)不需要再编写繁复的SQL 语句,针对实体类及其属性进行查询
2)查询结果是直接存放在List 中的对象,不需要再次封装
3)独立于数据库,对不同的数据库根据Hibernate dialect 属性的配置自动生成不同的SQL 语句执行
[select/update/delete……] from Entity [where……] [group by……] [having……] [order by……]
3.使用HQL查询语言
1)得到Session
2)编写HQL语句
3)创建Query对象
Query是HQL查询接口它提供了各种查询功能
4)执行查询,得到结果
实例:
Configuration conf=null;
SessionFactory sessionFatory=null;
Session session=null;
try {
sessionFactory=newConfiguration().configure().buildSes sion;
session = sessionFactory.openSession();
String hql = “from Street”;
Query query = session.createQuery(hql);
List<Street> list = query.list();
for(Street street:list){
System.out.println("街道名称" +
street.getDistrict().getName()+"区"
+street.getName());
}
} catch (HibernateException e) {
e.printStackTrace();
} finally{
// 省略部分代码
}
其中“from Street”中可以写类名也可以写类的完全限定名“from cn.jbit.houserent.been.Street”相同。
HQL中使用的Java 的类名和属性名的大小写是区分的。
其他的关键字是大小写是不区分的。
3.设置别名
“from Street as s”
其中s是Street 的别名,通过as关键字指定,as是可选的4.实体查询
1)where字句
我们可以通过与SQL相同的比较符指定条件,如
==、<>、< >、>=、<=、between、in、not in、is、like等from house as h where(h.price%2000=1);
可以通过and、or等逻辑连接符组合各个逻辑表达式
from house as h where (h.price>2000) and (h.title=’中关村房屋出售’);
5.属性查询
1)查询实体对象的单个属性(数据库表中的某个字段信息)
“select user.password from User as user where =’admin’”
2)获取实体的多个属性
“select user.id ,user.password from User as user where
=’admin’”;
3)获取属性类型
String hql=”select user.id where User as user where name=’admin’”
Query query =session.createQuery(hql);
for(Iterator iter=query.list().iterator();iter.hasNext();)
{
User user=(User)iter.next();
System.out.println(“id的数据类型:”+user.getClass());
}
6. 参数绑定
1)”?”占位符
使用”?”作为占位符,可以先设定查询参数,通过setType()方法设置指定的参数,必须保证每个占位符都设置了参数,必须按照”?”所设定顺序设定,下标从0开始,而不是使用PreparedStatement对象时的从1开始,
String hql =”from User u where =?”;
Query query=session.createQuery(hql);
query.setString(0,”admin”);
2)命名参数
:name命名参数,标识一个名为name的查询参数,根据此参数进行参数设定,不需要按照特定的顺序
String hql =”from User u where =:name and u.password=:password”;
Query query=session.createQuery(hql);
query.setString(“password”,”111”);
query.setString(“name”,”admin”);
3)封装参数
动态设置查询参数,将参数封装为一个bean,通过Query 对象的setProperties(Object bean) 实现参数的设定
//封装查询参数
User user=new User();
user.setName(“admin”);
user.setPassword(“111”);
String hql=”from User u where =:name and u.password=:password”;
Query query=session.createQuery(hql);
query.setProperties(user);
7. HQL常用的聚合函数
1)count():统计函数
select count(u) from User as u
2)max() 和min():最大值和最小值函数
select max(h.price),min(h.price) from House h
3)avg() 和sum():平均值和求和函数
select avg(h.price),sum(h.floorage) from House h where
er_id= '1000'
8.排序
与SQL类似,HQL通过order by 字句实现对查询结果的排序
from User u order by u.id
默认为升序(desc 降序,asc升序),order by子句可指定多个排序条件
from House house order by house.price , house.floorage 9.分组
通过group by 子句获得一系列统计数据,并使用having子句对group by返回的结果集进行筛选。
select sum(house.floorage) from House house group by house.street_id having sum(house.floorage) > 1000
10.分页
Query提供了简单的分页方法
setFirstResult(int firstResult)方法,设置第一条记录的位置setMaxResults(int maxResults)方法,设置最大返回的记录数query.setFirstResult((pageIndex-1)*pageSize);
query.setMaxResults(pageSize);
List result=query.list();
11. 子查询
Hibernate子查询必须用圆括号包围必须出现在where子句中
select * from House as h1 where h1.price > (select avg(h2.price) from House h2 where h2.street_id = '1000')
第四章HQL进阶
1.HQL查询性能优化
1)避免or操作
多数情况下,如果where字句中条件包含or操作,那么
执行时将不使用索引。
某些环境可以使用in代替or
2)避免使用not
如果where子句包含not关键字,那么执行是该字段的索引失效,使用比较运算符替代not操作
3)避免like的特殊形式
如果like以一个“%”或“-”开始,该字段的索引不起作用,只能通过改变索引字段的形式变相的解决
4)避免having字句
在分组的查询语句中,尽量在where子句中指定条件
5)避免使用distinct
指定district会导致在结果中删除重复行。
因此在不要求
或允许冗余时,应避免使用distinct
2.数据加载方式
1)即时加载
当实体加载完成后,立即加载其关联数据
2)延迟加载
延迟加载即机制是为了避免一些无谓的性能开销而提取出来的,所谓延迟加载就是当在正正需要数据的时候,才真正执行数据加载操作,Hibernate提供了实体对象延迟加载、集合延迟加载、属性延迟加载。
类级别的默认加载方式是延迟加载。
集合延迟加载
<set name="employee"table="r_emp_pro"cascade="all"
lazy=”true”>
<key>
<column name="pro_id"not-null="true"/>
</key>
<many-to-many class="entity2.Employee"
column="emp_id"></many-to-many>
</set>
属性延迟加载
<property name="name"type="ng.String" lazy=”true”> <column name="name"length="20"not-null="true"/> </property>
实体对象延迟加载
<class name="entity2.Projects"table="projects"lazy=”true”> <id name="id"type="ng.Integer">
<column name="id"/>
<generator class="native"/>
</id>
<property name="name"type="ng.String">
<column name="name"length="20"not-null="true"/> </property>
<set name="employee"table="r_emp_pro"cascade="all">
<key>
<column name="pro_id"not-null="true"/>
</key>
<many-to-many class="entity2.Employee"
column="emp_id"></many-to-many>
</set>
</class>
3.list()方法和iterator()方法
1)使用list()方法获取查询结果,每次发出一条查询语句,获取全部信息
2)使用iterator()方法获取查询结果,先发出一条SQL 语句用来查询满足条件数据的id,然后依次按这些id查询记录,也就是按照N+1条SQL语句(N符合条件的记录数)list()方法
sessionFactory = new Configuration().configure().buildSessionFact ory();
session = sessionFactory.openSession();
Query query = session.createQuery("from House as h ");
System.out.println("使用list()方法查询数据");
List result1 = query.list();
for(int i=0;i<result1.size();i++){
House house = (House)result1.get(i);
System.out.println("标题:"+house.getTitle());
}
System.out.println("----------------------") ;
System.out.println("再一次执行list()方法"); List result2 = query.list();
for(int i=0;i<result2.size();i++){
House house = (House)result2.get(i);
System.out.println("标题:"+house.getTitle());
}
iterator()方法
sessionFactory = new Configuration().configure().buildSessionFact
ory();
session = sessionFactory.openSession(); Query query = session.createQuery("from House as h ");
System.out.println("使用iterate()方法查询数据");
Iterator it1 = query.iterate();
while(it1.hasNext()){
House house = (House)it1.next();
System.out.println("标题:"+house.getTitle());
}
System.out.println("----------------------") ;
System.out.println("再一次执行iterate()方法"); Iterator it2 = query.iterate();
while(it2.hasNext()){
House house = (House)it2.next();
System.out.println("标题:"+house.getTitle());
}
list()方法将不会在缓存中读取数据,它总是一次性的从数据库中直接查询所有符合条件数据,同时将获取数据写入缓存
iterator()方法则是获取了符合条件的的数据的id后,首先根据id在缓存中查找符合条件的数据,如缓存中没有,然后再到数据库中查询
4.HQL联接查询
1)内联接查询
语法:from Entity inner join [fetch] Entity.property
例:from District d inner join fetch
d.street s
2)外连接查询
左外联接:left join 或left outer join 例: from District d inner left fetch d.street s
右外联接: right join 或 right outer join 例:from District d inner right
d.street s
完整外连接: full join 或full outer join 5.命名查询
1)修改用户配置文件
<hibernate-mapping>
<class name="er" table="users">
<!--省略其他配置-->
</class>
<query name="loginUser">
<![CDATA[
from User u where =:name and u.password =:password
]]>
</query>
</hibernate-mapping>
<query>元素用于定义HQL查询语句,它和<Class>元素并列以<![DATA[HQL]]>方式保存HQL语句
在程序中通过Session对象的getNamedQuery()方法获取查询语句
Query query =session.getNamedQuery(“loginName”);
QueryUser qu=new QueryUser();
qu.setName(“admin”);
qu.setPassword(“admin”);
query.setProperties(qu);
6.本地SQL查询
Hibernate对本地SQL查询提供了内置的支持
1)Session的createSQLQuery()方法返回SQLQuery 对象
2)SQLQuery接口继承了Query接口
3)SQLQuery接口的addEntity()方法将查询结果的关系映射为对象
4)使用命名查询实现本地的SQL查询
1.使用<sql-query>元素定义本地SQL查询语句
2.与<class>元素并列
3.以<![CDATA[SQL]]> 方式保存SQL语句
4.使用<sql-query>元素的子元素<return>指定别
名和实体类的关系。
其中alias属性用于指定别名,class 属性用于指定实体类
5.通过Session对象的getNamedQuery()方法获取
查询语句
例1:本地SQL查询
String sql="select {d.*} from District d where ='清河'";
Query
query=sess.createSQLQuery(sql).addEntity("d",District.class);
System.out.println(query.list().size());
例2:通过命名查询实现本地SQL查询
映射文件添加
<sql-query name="allDistrict">
<![CDATA[select {d.*} from District d where ='清河']]> <return alias="d"class="entity1.District"></return> </sql-query>
应用程序调用:
Query query=sess.getNamedQuery("allDistrict");
System.out.println(query.list().size());。