ORM进阶:使用hql优化查询

本文详细介绍了Hibernate框架的基本使用方法,包括简单查询、带条件查询、分页查询及SQL语句查询等多种查询方式,并探讨了查询过程中可能遇到的问题及解决方案。

       前两次课,主要讲了使用hibernate建模,配置文件的编写。本节课,主要讲解,当hibernate架构已经搭建完成之后。如何使用框架。
       该框架的使用,主要就是对数据的读写。简化之前写sql语句的问题。

使用最多的查询种类

  • 简单查询
  • 带条件查询
  • 分页查询
  • sql语句查询

简单查询

       框架中的查询,面向的是实体对象,而不是数据库表。所以只需要指定要查询的字段即可:

Criteria criteria=session.createCriteria(类名.class);
criteria.add(Expression.like("要查询的属性名","*"));
List lst=criteria.list();

或使用hql语句查询:

Query query=session.createQuery("from 类名");
List lst=query.list();

当然以上两种查询,也可以添加参数。这样就可以精确查询了。

带参数的查询

       这一类的查询方法,与上面不同的就是,需要添加参数。有两种做法,一是拼接sql语句,然后执行。二是使用占位符。

第一种:

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

第二种:

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

为了避免sql注入的问题,我们常使用第二种方式。

分页查询

       hibernate的分页查询,可以说是非常方便的。如果是自己写sql语句,需要计算起始位置、查询条数。

List students= session.createQuery("from Student")
    .setFirstResult(1)  //从哪里开始
    .setMaxResults(2)   //每页显示的记录数
    .list();

       hql分页查询,只需要指出,从哪里开始,每页查询的记录数。就可以查询到需要的数据。

sql语句查询

       hibernate没有关闭使用sql语句查询。对于一些复杂的查询方法。我们仍然可以写sql语句进行查询。

Query query=session.createQuery("sql语句 ");

查询中遇到的问题

N+1问题:

       先看一个实例,有这样一组数据。班级和学生。 班级是一,学生是多。
这样的话,班级中的实体,大致应该如下:

public class Classes {  
    private int id; 
    private String name;
    private Set students;    //存放学生的集合  
}

       现在要做的操作是,查询某个班下的所有学生。按照正常的查询方式,查询大致如下:

//使用hql的迭代器
Iterator iter= session.createQuery("from Student").iterate();   
//打印 学生列表
while(iter.hasNext()){
    Student student=(Student)iter.next();
    System.out.println("student.name="+student.getName());
}

       执行以上的语句。可以查询到正确的结果。但是当你打印输出之后,你会发现。他发出的sql语句很多。如下:

N+1问题结果

       首先,发出一条语句,查询班级。然后在打印学生列表的时候,分别发出一条根据学生id查询学生的语句。共发出N+1条记录。所以说,这个问题,会影响效率。

解决方法:

//不实用hql迭代器,使用list()查询
List students= session.createQuery("from Student").list();
for(Iterator iter=students.iterator();iter.hasNext();){
    Student student=(Student)iter.next();
    System.out.println("student.name="+student.getName());
}

       唯一差别的地方就是,第一种方式使用的Iterate()查询,第二种方式是使用list()查询。

list()和iterate()有哪些区别呢?
       list:默认情况下list每次都会发出sql语句,list会讲数据放到缓存中,而不利用缓存
       Iterate:默认情况下Iterate利用缓存,如果缓存中不存在会先N+1问题

       hibernate是一个ORM框架。主要负责 实体对象与数据库的关系。为了提高查询效率,hibernate中支持延迟加载策略。即用的时候在发出sql查询。这样的话,才会出现N+1问题。
       当然也可以取消延迟加载,来避免N+1问题。只需要在相应标签中加一项配置 lazy=”false”即可。

<class name="com.test.vo.Classes" table="t_classes">
    <id name="id">
        <generator class="native"/>
    </id>
    <property name="name"/>
    //取消延迟加载,即查询班级的同时 连通 所有学生都查询出来
    <set name="students" lazy="false">  
        <key column="classesid"/>
        <one-to-many class="com.test.vo.Student"></one-to-many>
    </set>
</class>

       去除延迟加载,的确可以避免这种问题。但是,对于仅仅查询班级信息 来说,这样花费的代价 又太大了。

       针对不同的需求。hibernate提供了不同的方法。如:list()和Iterate()       get()和load()等

他们的区别在于,对缓存的利用。

总结

       在学习Hibernate的时候,最好将hibernate.show_sql属性配置上。这样就可以在控制台上看到hibernate生成的sql语句。这样配置,可以调试自己程序,进而优化查询效率。

评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值