- 浏览: 103058 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
4、报表查询
报表查询用于对数据分组和统计,完整的HQL语法:
[select...] from ... [where...] [group by... [having...]] [order by...]
4.1 投影查询
指查询结果仅包含部分实体或实体的部分属性。投影是通过select关键字实现。
from Customer c join c.orders o where o.orderNumber like 'T%'
//会检索出Customer 及关联的Order对象
select c from Customer c join c.orders o where o.orderNumber like 'T%'
//结果中只包含Customer对象
select c.id,c.name,o.orderNumber from Customer c join c.orders o where ...
//返回的list中,放的是Object[],对应选择的属性集合
4.1.1 动态实例化查询结果
select c.id,c.name,o.orderNumber from Customer c join c.orders o where ...
//返回的list中,放的是Object[],对应选择的属性集合
该查询结果返回的list集合存放的是关系数据,List中的每个元素代表查询结果的一条记录,可以定义一个CustomerRow类来包装这些记录,使程序代码能完全运用面向对象的语义来访问查询结果集。CustomerRow类采用JavaBean的形式,他的属性与Select语句中选择的实体的属性对应。
Iterator it = session.createQuery("select new mypack.CustomerRow(c.id,c.name,c.orderNumber) from Customer c join c.orders o where o.orderNumber like 'T%'").list().iterator();
while(it.hasNext()){
CustomerRow row = (CustomerRow)it.next();
}
4.1.2 过滤查询结果中的重复元素
select c.name from Customer c
返回的结果可能会有重复的名字,可以使用HashSet顾虑结果,或使用distinct关键字
select distinct c.name from Customer c
4.2 使用聚集函数
HQL查询语句中可调用的聚集函数:
a. count():统计记录条数
Integer count = (Integer)session.createQuery("select count(*) from Customer c").uniqueResult();
Integer count = (Integer)session.createQuery("select count(distinct c.name) from Customer c").uniqueResult();
b.min():求最小值
c.max():求最大值
Object [] os = (Object[])session.createQuery("select max(c.age),min(c.age) from Customer c").uniqueResult();
d.sum():求和
e.avg():求平均值
Float age = (Float)session.createQuery("select avg(c.age) from Customer c ").uniqueResult();
4.3 分组查询
(1)按照姓名分组,统计具有相同姓名的记录数目:
session.createQuery("select c.name,count(c) from Customer c group by c.name")
......
4.4 优化报表查询的性能
当select语句仅仅选择查询持久化类的部分属性时,Hibernate返回的查询结果为关系数据,而非持久化对象。eg:
from Customer c inner join c.orders o group by c.age
select c.Id,c.Name,c.age,o.ID,o.ORDER_NUMBER,o.CUSTOMER_ID from Customer c inner join c.orders c group by c.age
以上两条HQL能查询处相同的数据,不同的是,前者返回的是Customer和Order持久化对象,他们位于Session的缓存中;后者返回的是关系数据,不会占用session的缓存,可以被JVM回收。
报表查询一般会处理大量数据,如果使用第一种方式会导致大量Customer和Order持久化对象一直位于Session中,session还必须负责这些对象的同步,会降低性能!
5、高级查询技巧
5.1 动态查询
如果在程序运行前就明确了查询语句的内容(也称为静态查询),应该考虑HQL查询方式;但是如果只有在运行时才能明确查询语句的内容(也称为动态查询)QBC比HQL更加方便。
5.2 集合过滤
假设Customer的orders集合使用延迟策略,当调用customer.getOrders().iterator()方法,就会初始化orders集合,会加载所有与Customer关联的Order持久化对象。这种方式有两大不足:
a. 如果有1000个Order对象与Customer关联,就会加载1000个Order对象,而这些并不一定是都需要的,会因为加载多余的Order对象而影响性能。(如:访问价格大于100的Order对象)
b. 不能对orders集合排序
解决方法:
a. 通过HQL或QBC查询
session.createQuery("from Order o where o.customer= :customer and o.price>100 order by o.price");
b. 使用集合过滤
Query query = session.createFilter(customer.getOrders(),"where this.price>100 order by this.price")
session.createFilter()方法与你过来过虑集合,具有以下特点:
a. 返回Query类型的实例
b. 第一个参数指定一个持久化对象的集合,这个集合是否已经被初始化并没有关系,但是它所属的对象必须出于持久化状态
c. 第二个参数指定过滤条件,由HQL查询语句组成
d.不管持久化对象的集合是否已经被初始化,Query的list()方法都会进行查询,以上代码对应的SQL:
select ID,ORDER_NUMBER,PRICE from ORDERS where CUSTOMER_ID=1 and PRICE>100 order by PRICE;
e.如果Customer对象的orders集合已经被初始化,为了保证session的缓存中不会出现OID相同的Order对象,list()方法不会在创建Order对象,仅仅返回session中的引用。
f. 如果Customer对象的orders集合还没有被初始化,Query的list方法会创建相应的order对象,但是不会初始化Customer对象的orders集合。
集合过滤出了用于为集合排序或设置约束条件,还有其他用途:
(1)为Customer对象的orders集合分页
List result = session.createFilter(customer.getOrders(),"order by this.price asc")
.setFirstResult(10)
.setMaxResults(50)
.list();
(2)检索Customer对象的orders集合中Order对象的订单编号
List result = session.createFilter(customer.getOrders(),"selct this.orderNumber").list();
(3)检索数据库中与Customer对象的orders集合中Order对象的价格相同的所有Order对象:
List result = session.createFilter(customer.getOrders(),"select other from Order other where other.price = this.price").list();
(4)检索Order对象的lineItems集合中LineItem对象的Item
List result = session.createFilter(order.getLineItems(),"select this.item").list();
5.3 子查询
from Customer c where 1<(select count(o) from c.orders o )
子查询必须放在括号内。
(1)子查询可以分为相关子查询和无关子查询。相关子查询指子查询语句引用了外层查询语句定义的别名,而无关子查询指子查询语句与外层查询语句无关。
(2)HQL子查询依赖于底层数据库对子查询的支持能力。MySQL从4.1.x才开始支持子查询。如果希望应用程序能进行移植,应避免使用HQL的子查询功能。无关子查询语句可以改写为单独的查询语句,相关子查询语句可以改写为连接查询和分组查询。eg:
select c from Customer c join c.orders o group by c.id having count(o)>1
(3)如果子查询返回多条记录,可以用以下关键字来量化。
--all: 表示子查询返回的所有记录
--any: 表示子查询语句返回的任意一条记录
--some: 与'any'等价
--in: 与'any'等价
--exists: 表示子查询语句至少返回一条记录。
(4)如果子查询语句查询的是集合,HQL提供了缩写语法,eg:
Iterator it = session.createQuery("from Customer c where
rder in elements(c.orders)")
.setEntity("order",order)
.list()
.iterator();
以上elements()函数等价于一个子查询语句:
from Customer c where
rder in (from c.orders)
HQL提供了一组操作集合的函数或者属性
--size函数或size属性:获得集合中元素的数目
--minIndex函数或属性:对于建立了索引的集合,获得最小的索引
--maxIndex函数或属性:对于建立了索引的集合,获得最大的索引
--minElement函数或属性:对于包含基本类型元素的集合,获得集合中取值最小的元素
--maxElement函数或属性:对于包含基本类型元素的集合,获得集合中取值最大的元素
--elements函数:获得集合中所有的元素
from Customer c where c.orders.size>0 or
from Customer c where size(c.orders)>0
5.4 本地SQL查询
为了把SQL查询返回的关系数据映射为对象,需要在SQL查询语句中为字段指定别名。
String sql = "select cs.ID as {c.id},cs.NAME as {c.name},cs.AGE as {c.age} from CUSTOMERS cs where cs.ID=1";
Query query = session.createSQLQuery(sql,"c",Customer.class);
// session.createSQLQuery(sql,"类别名",Customer.class);类的别名必须位于大括号里。
String sql = "select {c.*},{o,*} from CUSTOMERS c inner join ORDERS o where c.ID=o.CUSTOMER_ID";
Query query = session.createSQLQuery(sql,new String[]{"c","o"},new Class[]{Customer.class,Order.class});
SQL放入映射文件中:
<sql-query name="findCustomersAndOrders"><![CDATA[
select {c.*},{o,*} from CUSTOMERS c inner join ORDERS o where c.ID=o.CUSTOMER_ID]]>
<return alias="c" class="Customer"/>
<return alias="o" class="Order"/>
</sql-query>
6.查询性能优化
Hibernate主要从以下几方面来优化查询性能
(1)降低访问数据库的频率,减少select语句的数目,实现手段包括:
a.使用迫切左外连接或迫切内连接检索策略
b.对延迟检索或立即检索策略设置批量检索数目
c.使用查询缓存
(2)避免多余加载程序不需要访问的数据,手段:
a.使用延迟检索策略
b.使用集合过滤
(3)避免报表查询数据占用缓存,实现手段为利用投影查询功能,查询出实体的部分属性。
(4)减少select语句中的字段,从而降低访问数据库的数据量,实现手段为利用Query的iterate()方法。
6.1 iterate()方法
Query接口的iterate()方法和list()方法都能执行SQL查询语句,但是前者在有些情况下能轻微提高查询性能。
iterate方法首先到数据库中检索ID字段,然后根据ID字段到Hibernate的第一级缓存以及第二季缓存中查找匹配的对象,如果存在就直接加入到查询结果集中,否则就执行额外的select语句,根据ID字段到数据库中查询该对象。而list方法会检索出所有的数据,只是如果ID对应的对象存在缓存中就不再进行封装了,直接返回。
6.2 查询缓存
对于查询语句,如果启用了查询缓存,当第一次执行查询语句时,hibernate会把查询结果存放在第二级缓存中,以后再次执行该查询语句时,只需从缓存中获得查询结果,从而提高查询性能!
注:如果查询结果中包含实体,第二级缓存只会存放实体的OID,而对于投影查询,第二级缓存会存放所有的数据值。
查询缓存适合于以下场合:
a.在应用程序运行时经常使用的查询语句
b.很少对查询语句关联的数据库数据进行插入、删除、更新操作
对查询语句启用查询缓存的步骤如下:
(1)配置第二级缓存
(2)在Hibernate的hibernate.properties配制文件中设置查询缓存属性:
hibernate.cache.use_query_catch=true;
(3)设置了第二步还不够,在执行时还不会启用查询缓存。对于希望启用查询缓存的查询语句,应该调用Query的setCatchable(true),启用对该查询语句的缓存。如果希望更加精力度的控制查询缓存,可以设置缓存区域:
query.setCatcheRegion("customerQueries");
Hibernate提供了三种和查询相关的缓存区域:
a.默认的查询缓存区域:cache.StandardQueryCache
b.用户自定义的查询缓存区域(也叫命名缓存)//query.setCatcheRegion("customerQueries");
c.时间戳缓存区域:cache.UpdateTimestampCache.
a、b都用于存放查询结果,而c存放了对与查询结果相关的表进行了插入、更新、删除操作的时间戳。Hibernate通过c类判断缓存的查询结果是否过期,运行过程如下:
(1)在T1时刻执行查询语句,把查询结果存放在QueryCache区域,该区域的时间戳为T1时刻
(2)在T2时刻对与查询结果相关的表进行插入、更新、删除操作,Hibernate把T2时刻存放在UpdateTimestampCache区域。
(3)在T3时刻执行查询语句前,先比较QueryCache区域的时间戳河UpdateTimestampCache区域的时间戳,如果T2>T1,那么就丢弃存放在QueryCache区域的查询结果,重新到数据库中查询数据,再把结果放到QueryCache区域,否则直接返回查询结果。
可见,当前应用程序会自动刷新缓存的结果,但是如果其他应用程序对数据库进行了修改,Hibernate无法检测这一变化,此时必须由应用程序负责监测这一变化,然后手工刷新查询结果。Query.setForceCacheRefresh(true)方法允许手工刷新结果。
7、小结
发表评论
-
Hibernate入门
2010-10-27 00:11 735Java代码 1.public class User { ... -
hibernate二级缓存攻略
2010-10-20 15:31 617很多人对二级缓存都不太了解,或者是有错误的认识,我一直想写一篇 ... -
精通hibernate学习笔记(8)[检索方式]
2010-10-19 13:00 791提供的检索方式: (1)导航对象图检索方式 (2)OID ... -
精通hibernate学习笔记(7)[检索策略]
2010-10-19 12:55 810Customer和Order为例 1、hibernate检索 ... -
精通hibernate学习笔记(6)[映射类型]
2010-10-19 12:51 776Hibernate映射类型分为两种:内置映射类型和客户化映射类 ... -
精通hibernate学习笔记(4)[操作持久化对象]
2010-10-19 12:47 7131、理解Session的缓存 如果希望一个java对象一直处 ... -
精通hibernate学习笔记(5)[映射组成关系]
2010-10-19 12:46 8781、概念 1.1 聚集关系 在域模型中,有些类由几个 ... -
精通hibernate学习笔记(3)[关联关系]
2010-10-19 12:43 930关联关系分:单向关联 ... -
精通hibernate学习笔记(2)[标志符生成器]
2010-10-19 12:37 5941、increment 标识符生成器 该生成器由Hiber ... -
精通hibernate学习笔记(1)
2010-10-19 12:36 774实体域对象的 持久化模式 1、ORM模式 对象-关 ... -
分析Hibernate的缓存机制
2010-10-19 12:33 628缓存是介于应用程序和 ... -
Hibernate缓存管理
2010-10-19 12:31 6081. Cache简介: 缓存( ... -
Hibernate 学习笔记
2010-10-19 12:28 805原创 hibernate 笔记 收藏 day1 一. h ...
相关推荐
hibernate-commons-annotations-4.0.1.Final.jar hibernate-core-4.1.12.Final.jar hibernate-ehcache-4.1.12.Final.jar hibernate-entitymanager-4.1.12.Final.jar hibernate-jpa-2.0-api-1.0.1.Final.jar ...
8. **部署与配置**:帮助用户配置Hibernate项目,包括SessionFactory的生成,事务管理等。 Eclipse Hibernate Tools的4.1.1.Final版本于2013年12月发布,这个版本可能修复了一些已知问题,提升了稳定性和性能。对于...
hibernate-jpa-2.1-api-1.0.0.final-sources.jar 源码 hibernate-jpa-2.1-api-1.0.0.final-sources.jar 源码
检索方式及策略”这一主题中,我们将深入探讨如何在Hibernate 5中有效地检索数据以及相关的检索策略。 一、Hibernate检索方式 1. **HQL(Hibernate Query Language)**: HQL是Hibernate提供的面向对象的查询语言,...
Struts、Spring 和 Hibernate 是Java开发中非常著名的三个开源框架,它们在企业级应用开发中起着关键作用。Struts 是一个 MVC(Model-View-Controller)架构的 Web 框架,Spring 提供了一个全面的后端服务管理平台,...
《深入理解Hibernate配置与映射:hibernate-configuration-3.0.dtd与hibernate-mapping-3.0.dtd解析》 在Java世界里,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。而`hibernate-...
Hibernate学习笔记整理 以下是 Hibernate 框架的详细知识点: Hibernate 介绍 Hibernate 是一个 ORM(Object-Relational Mapping)框架,用于将 Java 对象映射到数据库表中。它提供了一个简洁的方式来访问和操作...
《Hibernate学习笔记特别详细》 Hibernate,作为一款开源的Object-Relational Mapping(ORM)框架,为Java开发者提供了强大的数据库操作支持。它简化了数据库访问的复杂性,使得开发人员可以像操作对象一样操作...
Hibernate学习笔记 Hibernate学习笔记 Hibernate学习笔记 Hibernate学习笔记
《Hibernate Tools更新4.1.1.Final版详解与应用》 Hibernate Tools是开发者在使用Hibernate框架进行Java应用程序开发时的重要辅助工具,它为Eclipse IDE提供了强大的集成支持,包括对象关系映射(ORM)的可视化设计...
通过学习和掌握Hibernate的检索方式以及查询优化技巧,开发者能够更高效地与数据库交互,提高应用的性能。对于源码分析,理解Hibernate内部如何处理查询请求,以及如何通过工具(如Eclipse或IntelliJ IDEA的插件)...
在本文中,我们将深入探讨`hibernate-commons-annotations-5.0.1.Final.jar`的源码,了解其内部结构和主要功能。 一、元数据注解 HCA的核心在于提供了一系列的注解,如`@Entity`、`@Table`、`@Column`、`@Id`等,...
hibernate-jpa-2.0-api-1.0.1.Final-sources.jar hibernate jpa 源代码
使用hibernate-validator 进行校验的jar包,里面包括了基础hibernate-validator-5.0.0.CR2.jar hibernate-validator-annotation-processor-5.0.0.CR2.jar 之外,还包括了el-api-2.2.jar javax.el-2.2.4等项目必不可...
hibernate-jpa-2.0-api-1.0.1.Final.jar
1. **环境搭建**:首先,我们需要配置Hibernate的核心库,包括hibernate-core、junit等依赖,通过Maven或Gradle等构建工具添加到项目中。 2. **实体类创建**:在Java中定义一个实体类,例如User,它代表数据库中的...
Hibernate稳定版(hibernate-release-5.3.23.Final.zip),Hibernate ORM 是一个为应用程序、库和框架提供对象/关系映射 (ORM) 支持的库。它还提供了 JPA 规范的实现,这是 ORM 的标准 Java 规范。
精通hibernate-孙卫琴,精通hibernate-孙卫琴,精通hibernate-孙卫琴,精通hibernate-孙卫琴
达梦数据DmDialect-for-hibernate所有jar包,DmDialect-for-hibernate2.0、DmDialect-for-hibernate2.1、DmDialect-for-hibernate3.0、DmDialect-for-hibernate3.1、DmDialect-for-hibernate3.6、DmDialect-for-...
2. **库文件**:包含jar包,如hibernate-core.jar、hibernate-entitymanager.jar等,这些是我们在项目中引入Hibernate时需要用到的依赖库。 3. **文档**:通常包括用户指南、API文档、开发者文档等,这些文档提供了...