Hibernate查询快速入门

如果不知道所要寻找的对象的持久化标识,那么你需要使用Hibernate查询。在这里拿出来和大家分享一下我的经验,希望对大家有用。

Hibernate支持强大且易于使用的面向对象查询语言(HQL)。 如果希望通过编程的方式创建查询,Hibernate提供了完善的按条件(Query By Criteria, QBC)以及按样例(Query By Example, QBE)进行Hibernate查询的功能。 你也可以用原生SQL(native SQL)描述Hibernate查询,Hibernate额外提供了将结果集(result set)转化为对象的支持。

执行查询

HQL和原生SQL(native SQL)查询要通过为org.hibernate.Query的实例来表达。 这个接口提供了参数绑定、结果集处理以及运行实际查询的方法。 你总是可以通过当前Session获取一个Query对象:

 
 
 
  1. List cats = session.createQuery(
  2.     "from Cat as cat where cat.birthdate < ?")
  3.     .setDate(0, date)
  4.     .list();
  5. List mothers = session.createQuery(
  6.     "select mother from Cat as cat join cat.mother as mother where cat.name = ?")
  7.     .setString(0, name)
  8.     .list();
  9. List kittens = session.createQuery(
  10.     "from Cat as cat where cat.mother = ?")
  11.     .setEntity(0, pk)
  12.     .list();
  13. Cat mother = (Cat) session.createQuery(
  14.     "select cat.mother from Cat as cat where cat = ?")
  15.     .setEntity(0, izi)
  16.     .uniqueResult();]]
  17. Query mothersWithKittens = (Cat) session.createQuery(
  18.     "select mother from Cat as mother left join fetch mother.kittens");
  19. Set uniqueMothers = new HashSet(mothersWithKittens.list());

一个查询通常在调用list()时被执行,执行结果会完全装载进内存中的一个集合(collection)。 查询返回的对象处于持久(persistent)状态。如果你知道的查询只会返回一个对象,可使用list()的快捷方式uniqueResult()。 注意,使用集合预先抓取的查询往往会返回多次根对象(他们的集合类都被初始化了)。你可以通过一个集合来过滤这些重复对象。

1. 迭代式获取结果(Iterating results)

某些情况下,你可以使用iterate()方法得到更好的性能。 这通常是你预期返回的结果在session,或二级缓存(second-level cache)中已经存在时的情况。 如若不然,iterate()会比list()慢,而且可能简单查询也需要进行多次数据库访问: iterate()会首先使用1条语句得到所有对象的持久化标识(identifiers),再根据持久化标识执行n条附加的select语句实例化实际的对象。

 
 
 
  1. // fetch ids
  2. Iterator iter = sess.createQuery("from eg.Qux q order by q.likeliness").iterate();
  3. while ( iter.hasNext() ) {
  4.     Qux qux = (Qux) iter.next();  // fetch the object
  5.     // something we couldnt express in the query
  6.     if ( qux.calculateComplicatedAlgorithm() ) {
  7.         // delete the current instance
  8.         iter.remove();
  9.         // dont need to process the rest
  10.         break;
  11.     }
  12. }

2. 返回元组(tuples)的查询

(译注:元组(tuples)指一条结果行包含多个对象) Hibernate查询有时返回元组(tuples),每个元组(tuples)以数组的形式返回:

 
 
 
  1. Iterator kittensAndMothers = sess.createQuery(
  2.             "select kitten, mother from Cat kitten join kitten.mother mother")
  3.             .list()
  4.             .iterator();
  5. while ( kittensAndMothers.hasNext() ) {
  6.     Object[] tuple = (Object[]) kittensAndMothers.next();
  7.     Cat kitten  = tuple[0];
  8.     Cat mother  = tuple[1];
  9.     ....
  10. }

3. 标量(Scalar)结果

查询可在select从句中指定类的属性,甚至可以调用SQL统计(aggregate)函数。 属性或统计结果被认定为"标量(Scalar)"的结果(而不是持久(persistent state)的实体)。

 
 
 
  1. Iterator results = sess.createQuery(
  2.         "select cat.color, min(cat.birthdate), count(cat) from Cat cat " +
  3.         "group by cat.color")
  4.         .list()
  5.         .iterator();
  6.         
  7. while ( results.hasNext() ) {
  8.     Object[] row = (Object[]) results.next();
  9.     Color type = (Color) row[0];
  10.     Date oldest = (Date) row[1];
  11.     Integer count = (Integer) row[2];
  12.     .....
  13. }

4. 绑定参数

接口Query提供了对命名参数(named parameters)、JDBC风格的问号(?)参数进行绑定的方法。 不同于JDBC,Hibernate对参数从0开始计数。 命名参数(named parameters)在查询字符串中是形如:name的标识符。 命名参数(named parameters)的优点是:

命名参数(named parameters)与其在查询串中出现的顺序无关

它们可在同一查询串中多次出现

它们本身是自我说明的

 
 
 
  1. //named parameter (preferred)
  2. Query q = sess.createQuery("from DomesticCat cat where cat.name = :name");
  3. q.setString("name", "Fritz");
  4. Iterator cats = q.iterate();
  5. //positional parameter
  6. Query q = sess.createQuery("from DomesticCat cat where cat.name = ?");
  7. q.setString(0, "Izi");
  8. Iterator cats = q.iterate();
  9. //named parameter list
  10. List names = new ArrayList();
  11. names.add("Izi");
  12. names.add("Fritz");
  13. Query q = sess.createQuery("from DomesticCat cat where cat.name in (:namesList)");
  14. q.setParameterList("namesList", names);
  15. List cats = q.list();

5. 分页

如果你需要指定结果集的范围(希望返回的***行数/或开始的行数),应该使用Query接口提供的方法:

 
 
 
  1. Query q = sess.createQuery("from DomesticCat cat");
  2. q.setFirstResult(20);
  3. q.setMaxResults(10);
  4. List cats = q.list();

Hibernate 知道如何将这个有限定条件的查询转换成你的数据库的原生SQL(native SQL)。

6. 可滚动遍历(Scrollable iteration)

如果你的JDBC驱动支持可滚动的ResuleSet,Query接口可以使用ScrollableResults,允许你在查询结果中灵活游走。

 
 
 
  1. Query q = sess.createQuery("select cat.name, cat from DomesticCat cat " +
  2.                             "order by cat.name");
  3. ScrollableResults cats = q.scroll();
  4. if ( cats.first() ) {
  5.     // find the first name on each page of an alphabetical list of cats by name
  6.     firstNamesOfPages = new ArrayList();
  7.     do {
  8.         String name = cats.getString(0);
  9.         firstNamesOfPages.add(name);
  10.     }
  11.     while ( cats.scroll(PAGE_SIZE) );
  12.     // Now get the first page of cats
  13.     pageOfCats = new ArrayList();
  14.     cats.beforeFirst();
  15.     int i=0;
  16.     while( ( PAGE_SIZE > i++ ) && cats.next() ) pageOfCats.add( cats.get(1) );
  17. }
  18. cats.close()

请注意,使用此功能需要保持数据库连接(以及游标(cursor))处于一直打开状态。 如果你需要断开连接使用分页功能,请使用setMaxResult()/setFirstResult()

7. 外置命名查询(Externalizing named queries)

你可以在映射文件中定义命名查询(named queries)。 (如果你的查询串中包含可能被解释为XML标记(markup)的字符,别忘了用CDATA包裹起来。)

参数绑定及执行以编程方式(programatically)完成:

 
 
 
  1. Query q = sess.getNamedQuery("ByNameAndMaximumWeight");
  2. q.setString(0, name);
  3. q.setInt(1, minWeight);
  4. List cats = q.list();

请注意实际的程序代码与所用的查询语言无关,你也可在元数据中定义原生SQL(native SQL)查询, 或将原有的其他的查询语句放在配置文件中,这样就可以让Hibernate统一管理,达到迁移的目的。

也请注意在 元素中声明的查询必须有一个全局唯一的名字,而在 元素中声明的查询自动具有全局名,是通过类的全名加以限定的。比如eg.Cat.ByNameAndMaximumWeight。

分享标题:Hibernate查询快速入门
转载注明:http://www.shufengxianlan.com/qtweb/news10/338510.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联