zoukankan      html  css  js  c++  java
  • Hibernate的检索方式(五)【转】

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://aumy2008.blogbus.com/logs/14096736.html

    五、高级查询技巧

     

    2、集合过滤

           延迟检索策略――customer.getOrders().iterator() (加载关联对象集合),这种方式的不足:

    l         全部加载

    l         不能排序

     

    2种办法可以解决上边不足,一种是通过HQLQBC查询orders集合,还有一种办法就是使用集合过滤

     

    集合过滤示例:

        List result=session.createFilter(customer.getOrders(),           "where this.price>200 order by this.price").list();    Iterator it=result.iterator();    while(it.hasNext()){       Order order =(Order)it.next();       .....

        }

     

           SessioncreateFilter()方法用来过滤集合,它具有以下特定。

    l         返回Qurey类型的实例。

    l         第一个参数:指定一个持久化对象的集合,这个集合是否已经被初始化并没有关系,但它所属的对象必须处于持久化状态。否则抛出异常。

    l         第二个参数:指定过滤条件,它由合法的HQL查询语句组成。

    l         不管持久化对象的集合是否已经初始化,Querylist()方法都会执行SQL查询语句,到数据库中检索Order对象。

    l         如果对象的集合已经被初始化,为了保证Session的缓存中不会出现OID相同的Order对象,Querylist()方法不会再创建Order对象,仅仅返回已经存在的Order对象的引用。

    l         如果没有初始化,Querylist()方法创建相应的对象,但不会初始化所给对象的集合。(仅仅取出符合条件的对象集合,是对象集合的子集)

     

    集合过滤的几个应用:

    A、为集合排序或设置约束条件

    B、 集合分页

    C、 检索集合中对象的某个属性

    D、检索数据库中与Customer对象的orders集合中的Order对象的属性(一个或多个)相同的所有Order对象

    E、 检索Order对象的lineItems集合中LineItem对象的Item

     

    代码示例:

         List result=session.createFilter(customer.getOrders(),        " order by this.price asc")        .setFirstResult(10)        .setMaxResults(5)        .list();          List result=session.createFilter(customer.getOrders(),        "select this.orderNumber")        .list();          List result=session.createFilter(customer.getOrders(),        "select other from Order other where other.price=this.price")        .list();          List result=session.createFilter(order.getLineItems(),        "select this.item")

            .list();

     

    3、子查询

           HQL支持where子句中嵌入查询语句。

    from Customer c where 1<(select count(o) from c.orders o) ――相关子查询

    from Order o where o.price>(select avg(o1.price) from Order o1) 无关

     

           关于子查询的用法说明:

           1)、子查询可以分为相关子查询和无关子查询。

           2)、依赖底层数据库对子查询的支持能力。

           3)、如果子查询语句返回多条记录,可以用一下关键字来衡量。

    l         all:表示子查询语句返回的所有记录。

    l         any:任意一条记录。

    l         some:与“any”等价。

    l         in:与“=any”等价。

    l         exists:至少返回一条记录。

    例:订单的价格都不小于100的客户

    from Customer c where 100>all (select o.price from c.orders o)

    有一条订单的价格小于100的客户

    from Customer c where 100>any (select o.price from c.orders o)

    有一条订单的价格等于100的客户

    from Customer c where 100=some (select o.price from c.orders o)

    from Customer c where 100=any (select o.price from c.orders o)

    from Customer c where 100 in (select o.price from c.orders o)

    至少有一条订单的客户

    from Customer c where exsist (from c.orders)

     

    4)、如果子查询语句查询的是集合,HQL提供了所写语法

         Iterator it=session.createQurey(               "from Customer c where :order in element(c.orders)")                  .setEntity("order",order)                  .list()

                      .iterator();

           element(c.orders)等价于(from c.orders

     

           HQL提供了一族操纵集合的函数或者属性。

    l         size()函数或size属性:获取集合中元素的数目。

    l         minIndex()函数或minIndex属性:对于建立了索引的集合,获取最小的索引。

    l         maxIndex()函数或maxIndex属性:对于建立了索引的集合,获取最大的索引。

    l         minElement()函数或minElement属性:对于包含基本类型元素的集合,获得集合中取值最小的元素。

    l         maxElement()函数或maxElement属性:对于包含基本类型元素的集合,获得集合中取值最大的元素。

    l         elements()函数:获得集合中所有元素。

     

    如:订单数目大于零的客户

    from Customer c where c.orders.size>0

    或者 from Customer c where size(c.orders)>0

      

    4、本地SQL查询

           Hibernate本地SQL查询提供了支持,为了把SQL查询返回的关系数据映射为对象,需要在SQL查询语句中为字段指定别名。

        String sql1 = "select cs.ID as {c.id},cs.name as {c.name} "           + "from CUSTOMERS cs where cs.ID=1";

        Query query = session.createSQLQurey(sql1, "c", Customer.class);

        String sql1 = "select {c.*} "       + "from CUSTOMERS c where c.ID=1";

        Query query = session.createSQLQurey(sql1, "c", Customer.class);

    多个不同的对象情况

    String sql1 = "select {c.*},{o.*} from CUSTOMERS c inner join ORDERS o"           + " where c.ID=o.CUSTOMER_ID";    Query query = session.createSQLQurey(sql1, new String[] { "c", "o" },

               new Class[] { Customer.class, Order.class });

     

           在程序中嵌入本地SQL语句会增加维护程序代码的难度,如果数据库表的结构发生变化,必须修改相应的程序代码,因此更合理的方式是把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>

      

    六、查询性能优化

    1、 降低访问数据库的频率,减少select语句的数目。实现手段包括:

    l         使用迫切左外连接或迫切内连接检索策略。

    l         对延迟加载或立即加载策略设置批量检索数目。

    l         使用查询缓存。

    2、避免多余加载程序不需要访问的数据。实现手段包括:

    l         使用延迟检索策略。

    l         使用集合过滤。

    3、 避免报表查询数据占用缓存。实现手段为利用投影查询功能,查询出实体的部分属性。

    4、减少select语句中的字段,从而降低访问数据库的数据量。实现手段为利用Queryiterate()方法。

      

    iterate()方法:

           Query接口的iterate()方法和list()方法都能执行SQL查询语句。

           list()首先检索ID字段,然后根据ID字段到Hibernate第一缓存以及第二级缓存中查找匹配的对象,如果存在,就直接把它加入到查询结果集中,否则就只想额外的select语句,根据ID字段数据库中检索该对象。

     

    查询缓存

           查询缓存适应以下场合:

    l         在应用程序运行时经常使用的查询语句。

    l         很少对与查询语句关联的数据库数据进行插入、删除或更新操作。

     

    查询语句启用查询缓存的步骤如下:

    A、配置第二级缓存。

    B、 Hibernatehibernate.properties配置文件中设置查询缓存属性:

    hibernate.cache.use_query_cache=true

           C、启用查询缓存。调用Query接口的setCacheable(true)方法。

     结束!
  • 相关阅读:
    焦点的相关属性和方法
    laravel 环境配置
    fetch body里数据为ReadableStream 解决办法
    解决NodeJS+Express模块的跨域访问控制问题:Access-Control-Allow-Origin
    mongo启动
    react-native android 打包发布
    delphi 还原窗口
    窗口还原
    款式修改窗口,开发调整过窗口格局保存功能,关了窗口重新打开还是按关闭前的格局.
    希尔排序算法
  • 原文地址:https://www.cnblogs.com/myssh/p/1438803.html
Copyright © 2011-2022 走看看