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属性来指定,指定关联查询数量,以减少批量检索的数据数目。

posted @ 2018-06-05 14:05  姚继新  阅读(108)  评论(0编辑  收藏