zoukankan      html  css  js  c++  java
  • Hibernate查询(HQL——Hibernate Query Language)

    HQL查询

      HQL提供了是十分强大的功能,它是针对持久化对象,用取得对象,而不进行update,delete和insert等操作。而且HQL是面向对象的,具备继承,多态和关联等特性。

    from子句:

      from子句是最简单的HQL,例如from Student,也可以写成 select s from Student s。它简单的返回Student类的所有实例。值得注意的是除了JAVA类和属性的名称外,HQL语句对大小写不敏感。

    select子句:

    有时并不需要取得对象的所有属性,这时可以使用select子句进行属性查询,如select s.name from Student s。

    统计函数查询

    可以在HQL中使用函数,经常使用的函数如下:

    count():统计记录条数。

    min():求最小值。

    max():求最大值。

    sum():求和。

    avg():求平均值。

    例,要取得Student实例的数量,可以编写如下HQL语句:

      select count(*) from Student

    取得Student平均年龄的HQL语句:

      select avg(s.age) from Student as s

    可以使用distinct去除重复的数据:

      select distinct s.age from Student as s

    where子句:

      HQL也支持子查询,它通过where子句实现这一机制。where子句可以让用户缩小要返回的实例的列表范围。例如下面语句会返回所有名字为"Bill"的Student实例:

      Query query = session.createQuery("from Student as s where s.name='Bill'");

    where子句允许出现的表达式包括了SQL中可以使用的大多数情况。

    常用操作符

    数学操作:+,-,*,/

    真假比较操作:=, >=, <=, <>, !=, like

    逻辑操作:and ,or, not

    字符串连接:||

    SQL标题函数 :如upper()和lower()

    如果查询返回多条记录,可以用以下关键字来量化

    all:表示所有的记录。

    any:表示所有记录中的任意一条。

    some:与any相同。

    in:与any等价。

    exists:表示子查询至少要返回一条记录。

    例如,下面语句返回所有学生年龄都大于18的班级对象

      from Group g where 18<all  (select s.age from g.students s)

    下列语句返回在所有学生中有一个学生的年龄等于22的班级:

      from Group g where 22 = any (select s.age from g.students s)

    或者

      from Group g where 22= some(select s.age from g.students s)

    或者

      from Group g where 22 in (select s.age from g.students s)

    连接查询

    与SQL一样,HQL也支持连接查询,如内连接,外连接和交叉连接:

    inner join:内连接

    left outer join:左外连接

    rigth outer join:右外连接

    full join:全连接,但不常用

    order by子句

    查询返回列表可以按照任何返回的类或者组件的属性排序

      from Student s order by s.name asc

    Criteria Query方式

      当查询数据时,往往需要设置查询条件。在SQL或HQL语句中,查询条件常常放在where子句中。此处Hibernate还支持Criteria查询,这种查询方式把查询条件封装为一个Criteria对象。在实际应用中,可以使用Session的createCriteria()方法构建一个org.hibernate.Criteria实例,然后把具体的查询条件通过Criteria的add方法加入到Criteria实例中。这样程序员可以在不使用SQL甚至HQL的情况下进行数据查询。

    常用的查询限制方法

    代码中 Restrictions.eq()方法表示equal,即等于的情况。Restrictions类提供了查询限制机制。它提供了许多方法,以实现查询限制

    Restrictions.eq():equal,=

    Restrictions.allEq(): 参数为Map对象,使用key/value进行多个等于的对比,相当于多个Restrictions.eq()的效果

    Restrictions.gt():greater-than: >

    Restrictions.lt():less-than:<

    Restrictions.le:less-equal:<=

    Restrictions.between():对应SQL的between子句。

    Restrictions.like():对应SQL的like子句。

    Restrictions.in():对应SQL的in子句。

    Restrictions.and():and 关系。

    Restrictions.or():or 关系。

    Restrictions.isNull():判断属性是否为空,为空返回true,否则返回false。

    Restrictions.isNoyNull():与上面的相反。

    Order.asc():根据传入的字段进行升序排序。

    Order.desc():与上相反

    MatchMode.EXACT:字符串中精确匹配,相当于like 'value'

    MatchMode.ANYWHERE:字符串在中间位置,相当于like'%value%'

    MatchMode.START:字符串在最前面,相当于like'value%'

    MatchMode.END:字符串在最后,相当于like'%value'

    下面是几个查询限制的例子:

    查询学生名字以t开关的所有Student对象

    Criteria criertia = session.createCriteria(Student.class);
    
    criteria.add(Restrictions.like("name", "t%"));
    
    List list
    = criteria.list(); Student stu = (Student)list.get(0);

    或者:

      Criteria criertia = session.createCriteria(Student.class);
    
      criteria.add(Restrictions.like("name", "t",MatchMode.START));
    
      List list = criteria.list();
    
      Student stu = (Student)list.get(0);

    查询学生姓名在Bill,Jack和Tom之间所有的Student对象

     String[] names = {"Bill","Jack","Tom"};
    
      Criteria criertia = session.createCriteria(Student.class);
    
      criteria.add(Restrictions.in("name", names));
    
      List list = criteria.list();
    
      Student stu = (Student)list.get(0);

    查询学生年龄(age)等于22或为空(null)的所有学生对象

    Criteria criertia = session.createCriteria(Student.class);
    
      criteria.add(Restrictions.eq("age", new Integer(22)));
    
      criteria.add(Restrictions.isNull("age"));
    
      List list = criteria.list();
    
      Student stu = (Student)list.get(0);

    查询学生姓名以字母F开头的所有Student对象,并按姓名升序排序

    Criteria criertia = session.createCriteria(Student.class);
    
      criteria.add(Restrictions.like("name", "F%"));
    
      criteria.addOrder(Order.asc("name"));
    
      List list = criteria.list();
    
      Student stu = (Student)list.get(0);

    注意调用Order.asc的方法应该是Criteria.addOrder()方法。

    连接限制

    Criteria查询中使用FetchMode来实现连接限制。在HQL语句中,可以通过fetch关键字来表示预先抓取(Eager fetching),如下:

    from Group g

    left join fetch g.students s

    where g.name like '%2005'

    可以使用Criteria的API完成同样的功能

    Native SQL查询

      本地SQL查询指的是直接使用本地数据库的SQL语言进行查询。这样做对于将原来的SQL/JDBC程序迁移到Hibernate应用很有用。创建一个基于SQL的Query Native SQL查询是通过SQLQuery接口来控制的,它通过调用Session.createSQLQuery()方法来获得。

    命名SQL查询

    与HQL的命名查询相似,也可以将 本地的SQK查询语句定义在映射文件中,然后像调用一个命名HQL查询一样专题报道调用命名SQL查询。

    Hibernate中Session接口

    1、Session的save()和persist()方法

    Session的save()方法使一个临时对象转变为持久化对象。它完成以下操作:

      (1)将临时对象加入到Session缓存中,使其进入持久化状态。

      (2)选用映射文件指定的标识符生成器,为持久化对象分配唯一的OID。

      (3)计划执行一个insert语句。 

    Session的save()方法是用来持久化临时对象的。不应将持久化对象或游离对象传递给save()方法。若将持久化对象传递给save()方法,则该步保存操作是多余的。若将游离对象传递给save()方法,则会重新生成OID,再保存一次。

    Session的persist()方法与save()方法类似,也能将临时对象转变为持久化对象。

    persist()方法与save()方法的区别在于:persist()方法不保证立即为持久化对象的OID赋值,而是有可能在Session清理缓存的时候才为OID赋值。此外,如果是在事物边界以外调用persist()方法,则该方法不会计划执行insert语句。而save()方法不论是在事物边界以外还是以内,都会计划执行insert语句。

    2、Session的load()与get()方法

    Session的load()与get()方法都能从根据给定的OID从数据库中加载一个持久化对象,这两个方法的区别在于:

    (1)当数据库中不存在与OID对应的记录时,load()方法抛出org.hibernate.ObjectNotFoundException异常,而get()方法返回为null。

    (2)load方法采用配置的加载策略(默认为延迟加载),而get()方法则会忽略配置,总是采用立即加载方法。

    3、Session的update()方法

    Session的update()方法使一个游离对象转变为持久化对象。它完成以下操作:

    (1)将游离对象加入到Session缓存中,使其转变为持久化对象。

    (2)计划执行一个update语句。

    当update()方法关联一个游离对象时,若在Session的缓存中已存在相同的OID的对象时,会抛出异常。

    4、Session的saveOrUpdate()方法

      Session的saveOrUpdate()方法同时包含了save()方法与update()方法的功能,如果传入的参数是临时对象,就调用save()方法;如果传入的参数是游离对象,就调用update()方法。HIbernate根据对象的OID,version版本属性等来判断参数是临时对象还是游离对象。

    5、Session的merge()方法

    Session的merge()方法能够将一个游离对象的属性复制到一个持久化对象中。其处理流程如下:

      (1)根据游离对象的OID到Session缓存中查找匹配的持久化对象。若找到匹配的持久化对象,则将游离对象的属性复制到持久化对象中,计划实行一条update语句,然后返回持久化对象的引用。

      (2)如果在Session的缓存中没有找到与游离对象OID一致的持久化对象,那么就试图根据该OID从数据库中加载持久化对象。如果数据库中存在匹配的持久化对象,则将游离对象的属性复制到刚加载的持久化对象中,计划实行一条update语句,然后返回持久化对象的引用。

      (3)如果数据库中也不存在or对象是临时对象时,则会新建一个对象,将属性赋值到该新建对象中,再持久化新建对象,最后返回新建对象的引用。

    merger()和saveOrUpdate()的区别:调用完meger()对象仍然是脱管状态。

    6、Session的delete()方法

    Session的delete()方法用于从数据库中删除一个java对象。delete()方法既可以删除持久化对象,也可以删除游离对象。其处理过程如下:

    (1)如果传入的参数是游离对象,则先使游离对象与Session关联,使它变为持久化对象。如果参数是持久化对象,则忽略该步。

    (2)计划执行一个delete语句。

    (3)把对象从Session缓存中删除,该对象进入删除状态。

    7、Session的replicate()方法

    Session的replicate()方法能够将一个数据库中的对象复制到另一个数据库中。

    Hibernate检索策略

      简介:  Hibernate的Session在加载一个Java对象时,可以将与这个对象相关联的其他Java对象都加载到缓存中,以便程序及时调用。但有些情况下,我们不需要加载太多无用的对象到缓存中,一来这样会撑爆内存,二来增加了访问数据库的次数。所以为了合理的使用缓存,Hibernate提供了几种检索策略来供用户选择。

    种类:立即检索策略、延迟检索策略、左外连接检索策略

    1、立即检索策略

    采用立即检索策略,会将被检索的对象,以及和这个对象关联的一对多对象都加载到缓存中。Session的get方法就使用的立即检索策略。

    优点:频繁使用的关联对象能够被加载到缓存中。

    缺点:1、占用内存。2、Select语句过多。

    2、延迟检索策略

      采用延迟检索策略,就不会加载关联对象的内容。直到第一次调用关联对象时,才去加载关联对象。在不涉及关联类操作时,延迟检索策略只适用于Session的load方法。涉及关联类操作时,延迟检索策略也能够适用于get,list等操作。在类级别操作时, 延迟检索策略,只加载类的OID不加载类的其他属性,只用当第一次访问其他属性时,才回访问数据库去加载内容。(这里使用了CGLIB生成了类的代理类)在关联级别操作时,延迟检索策略,只加载类本身,不加载关联类,直到第一次调用关联对象时,才去加载关联对象程序模式都是用延迟加载策略。如果需要指定使用延迟加载策略。在配置文件中设置<class>的lazy=true,<set>的lazy=true或extra(增强延迟)<many-to-one>的lazy=proxy和no-proxy。

    优点:由程序决定加载哪些类和内容,避免了大量无用的sql语句和内存消耗。

    缺点:在Session关闭后,就不能访问关联类对象了。 需要确保在Session.close方法前,调用关联对象。

    3、左外连接检索策略

    采用左外连接检索,能够使用Sql的外连接查询,将需要加载的关联对象加载在缓存中。

    <set>fetch设置为join,<many-to-one>的fetch设置为 join

    优点:对应用程序完全透明,不管对象处于持久化状态,还是游离状态,应用程序都可以方便的从一个对象导航到与它关联的对象。2.使用了外连接,select语句数目少。

    缺点:可能会加载应用程序不需要访问的对象,白白浪费许多内存空间。2.复杂的数据库表连接也会影响检索性能。

    batch-size属性:

    无论是立即检索还是延迟检索,都可以指定关联查询的数量,这就需要使用batch-size属性来指定,指定关联查询数量,以减少批量检索的数据数目。

  • 相关阅读:
    spring cloud的pigx版本
    SQL Profiler使用
    postmen简单用法
    T-SQL
    常见问题整理
    数据库 新建维护计划
    c# ABP返回格式自定义,去除固定返回格式
    系统综合实践期末大作业 第32组
    系统综合实践第7次实践作业 第32组
    系统综合实践第6次实践作业 第32组
  • 原文地址:https://www.cnblogs.com/yjxFive/p/9139488.html
Copyright © 2011-2022 走看看