hibernate 查询

本文深入探讨了Hibernate中多种查询方式的特点与应用场景,包括HQL、QBC、本地SQL等,详细介绍了每种方式的语法特点及如何进行条件设置、排序、分页等操作,并提供了查询性能优化的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文内容总结自  孙卫琴 精通Hibernate 电子工业出版社


对象图导航查询、OID查询、HQL、QBC、本地SQL

1、HQL 检索方式

     HQL 是   使用 hibernate  时使用最广的一种方式  功能如下

      a、查询语句中设定各种查询条件

      b、支持投影查询,即仅检索出对象的部分属性

      c、支持分页查询

      d、支持连接查询

      e、支持分组查询,having和groupBy

      f、提供内置聚集函数  sum、min、max

      g、能调用用户定义的SQL函数或标准SQL函数

      h、支持子查询

      i、支持动态绑定参数

      方法链编程风格

      List result=session.createQuery("from Customer as c where c.name=:customerName and c.age=:customerAge")

                                                    .setString("customerName","tom");

                                                    .setInteger("customerAge",21);

                                                    .list();



2、QBC(query by criteria)

     // Criteria criteria =session.createCtiteria(Customer.class);

    List result=session.createCriteria(Customer.class).add(Restrictions.like("name","T%")).add(Restirictions.eq("age",21))


  对结果集排序

       HQL:sessio.createQuery("from Customer c order by c.name");

      QBC: session.crateCriteria(Customer.class).addOrder(Order.asc("name"))

 分页查询

       HQL:session.createQuery(from Customer c order by c.name asc");    query.setFirstResult(0);  query.setMaxResult(10);

       QBC:sessiion.createCriteria(Customer.class).addOrder(Order.asc("name")).setFirstResult(0).setMaxResult(10).list();


 在HQL中调用函数  from Customer c where size(c.orders)>3

 检索不属于任何客户的订单 

       HQL:  from Order o where O.customer is null

       QBC: session.createCriteria(Order.class).add(Restrictions.isNull("customer"))


 查询以T开头以m结尾的customer对象

       HQL:"from Customer c were c.name like 'T%' and c.name like ‘%m"


连接查询

 a、迫切左外链接

      HQL:from Clazz c left join fetch c.students c where c.clazzId=1;

     QBC: session.createQuery(Clazz.class).setFetchMode("students",FetchMode.JOIN).addRestrictions.eq("clazzId",1);

   当使用迫切左外连接时,查询结果可能会包含重复元素,可以使用hashset去重

   在关联级别,我们通常使用默认的 lazy=true,在得到对象同时要得到其属性的场景下,我们即需要使用迫切左外连接

b、右连接

    from Clazz c left join c.students s where s.name like 'M%'

c、内连接

   from Clazz c,Student s where s.name like 'M%' and s.clazzId=c.clazzId


迫切左/右连接,返回的是单个对象的多条记录,左/右连接返回的是Object[ ]  迫切连接下many方会完成初始化,非迫切下不初始化

如果迫切左/右外连接的one方确定为一条记录,那么可以使用uniqueResult()方法,会将重复的记录合并



报表查询

    a、Long count=(Long)session.createQuery("select count(*) from tableName t").uniqueResult;

    b、Double age=(Double)session.createQuery(select avg(c.age) from User u).uniqueResult;

    c、Object[] os=(Object[])session.createQuery("select max(c.age),min(c.age) from User u")

    d、Long long=(Long)session.createQuery("select count(distinct u.name) from User u").uniqueResult();



优化报表查询性能

     当select 部分属性时,返回的是 关系数据,与session无关,可以被JVM回收,可以使用javabean封装数据

   select new package.ClazzRow(c.id,c.name,s.name) from Clazz c , c.students s where s.name like 'M%';

                                                             (构造)


group by

   a、Iterator it=session.createQuery("select s.gender ,count (s) from Student group by s.gender").list.iterator

      while(it.hasNext){

       Object  [] obj=(Object [ ]) it.next;

     String gender=(String)obj[0];

    Long count=(Long)obj(1);

    }

    b、"select c.id,c.name,count(s) from Clazz c left join c.studnets s group by c.id"

    c、"select c.id,c.name,sum(s.age) from Clazz c left join c.students s group by c.id"

   




查询技巧

    集合过滤

       经常遇到的场景时,先加载了oneToMany的one方,再加载many,而加载many时又需要加条件,这时可以使用集合过滤,传入的集合 处于hibernate4种状态那种无所谓,

     但其所属对象必须是持久状态,

   a 、List result=session.createFilter(clazz.getStudents(),"where this.name like ‘M%’" orderBy this.age).list();

    Iterator it=result.iterator();

   while(it.hasNext){

      Student s=(Student)it.next();

  }

   b、利用集合过滤器分页

     List result=session.createFilter(customer.getOrders(),"order by this.price asc").setFirstResult(10).setMaxResult(50).list();

   c、检索数据库中与customer对象的orders集合中order对象的订单编号

   List result=session.createFilter(customer.getOrders,"select this.orderNum").list;

   d、检索与Customer对象的orders集合中order对象价格相同的所有对象

    List result=session.crateFilter(customer.getOrders,"select other from Order other where other.price=this.price").list();

   e、假定order与lineitem(商品信息)一对多,Lineitem与item(商品)1对1,得到order的item

     List result=session.createFilter(order.getLineItems(),"select this.item").list();

   子查询

   a、查询有1条以上订单的客户

     from Customer c where 1<(select count(o) from c.orders o);

    b、查询订单价格大于平均价格的订单

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

    c、子查询关键字

       所有订单价格<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)

       有一个订单价格=10  from Customer c where 100 in (select o.price from c.order o)

   HQL 集合函数 size()、minIndex() maxIndex() minElement(0 maxElement elements()  ...

   查订单数大于0的客户   from Customer c where c.orders.size >0    OR  from Customer c where size(c.orders)>0


查询结果转换器  Criteria.ROOT_ENTITY,criteria.DIStINCT_ROOT_ENTITY,  criteria.ALIAS_TO_ENTITY_MAP

      a、确保查询结果不包含重复实例   (也可以通过使用hashset去重)

      session.createCriteria(Customer.class).setFetchMode("orders",FetchMode.JOIN).setResultTransFormer(Criteria.DISTINCT_ROOT_ENTITY).list()

      b、确保查询结果中包含根节点的实例及被关联的实例

         session.createCriteria(Customer.class).createAlias("orders","o").setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP).list();

    Iterator it=result.iterator();

   while(it.hasNext()){

    Map map=(Map)it.next();

    Customer customer=(Customer)map.get(Criteria.ROOT_ALIAS);

   Order order=(Order)map.get("o");

   

   }


查询性能优化

1、降低访问数据库的频率、减少select 语句数目

     a、使用迫切左外连接或迫切内连接

     b、对延迟检索或立即检索策略设置批量检索数目

     c、使用查询缓存

2、避免多余加载程序不许要访问的数据

    a、使用延迟检索策略

    b、使用集合过滤

3、避免报表查询占用缓存。利用投影查询,查询实体的部分属性

4、减少select 语句中的字段,从而将提访问数据库的数据量。(query的iterate())

A、session.createQuery(from Customer c).list();

      query2=session.createQuery(from Customer c where c.age>30).iterate();

  iterate()首先检索ID,然后根据ID到hibernate的1、2级缓存中找匹配的Customer对象,如果存在,就将其加入查询结果集,否则就执行额外的select语句,根据ID到数据库检索对象

5、查询缓存

     如果查询结果中包含实体,查询缓存只会存放实体的OID,投影查询(select new Constructo(...) from),会缓存所有的数据

    查询缓存适用场合:1、经常使用的查询语句 。2、很少对与查询语句检索到的数据进行插入删除或更新操作

     对查询语句启用查询缓存的步骤

        a、配置2级缓存

        b、在hibernate.properties中   hibernate.cache_query_cache=true

        c、session.createQuery(HQL).setCacheable(true);



3、本地SQL 

   有的应用可能需要根据底层数据库的SQL方言生成一些特殊的查询,这时使用本地SQL

   Query query=session.createSQLQuery("select * from USERS where USERNAME like :userName");

  


4、OID

5、对象图导航

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值