Java的Hibernate框架中Criteria查询使用的实例讲解

我们讲一下Criteria查询,这个对于不是太熟悉SQL语句的我们这些程序员来说是很容易上手的。
 废话不多说,看一下例子:
 实体类如下:

public class User implements Serializable{ 

  private static final long serialVersionUID = 1L;
  public Long id;
  private String name;
  private int age;
    //省略Get/Set方法
}

映射文件我们就不写了,很简单的一个实体,如果不懂的童鞋请参照我在hibernate分类中的其他文章。
 接下来我们看如何使用Criteria来进行查询:

public static void main(String[] args) { 

  Configuration cfg = new Configuration().configure();
  SessionFactory sessionFactory = cfg.buildSessionFactory();
  Session session = sessionFactory.openSession(); 

  Criteria criteria = session.createCriteria(User.class);
  criteria.add(Restrictions.eq("name","shun")); 

  List list = criteria.list();
  Iterator iter = list.iterator();
  while(iter.hasNext()) {
    User user = (User)iter.next();
    System.out.println(user.getName()+":"+user.getAge());
  } 

  session.close();
}

看到代码,很简单的一串。
 前面都很熟悉啦,我们看到构造session之后的代码:

Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("name","shun"));

这两句代码是重点,我们来分析一下,究竟是什么意思?
 第一句我们通过session得到Criteria实现类的一个对象,接着第二句我们通过add方法添加一个条件,eq表示相等。在Hibernate3以前是通过Expression.eq来实现,3之后由于Criteria被抛弃,我们改用Restrictions类来实现,它和Expression一样的用法。我们看看API发现Expression继承于Restrictions。
 回到我们上面的两句,我们做完这些工作后,实际上hibernate帮我们构造了类似

 select * from user where name='shun'

这样的语句。(这里我们映射文件中User类对应的表是user表,而name属性对应的是name字段)
 
 Restrictions还有许多帮助我们构造SQL语句的方法,大家查一下API很容易就可以理解了。
 
 我们重新看一下上面的代码,如果我们关闭了session,但是我们想继续使用这个criteria,行吗?我们来看一下。
 在上面的代码之后,我们重新遍历,加上:

List list2 = criteria.list();
Iterator iter2 = list.iterator();
while(iter.hasNext()) {
  User user = (User)iter.next();
  System.out.println(user.getName()+":"+user.getAge());
}

为了区分跟上一个list和iter的区别,我们这里用另外一个。
 运行它,我们得到的是一个异常:

org.hibernate.SessionException: Session is closed!

报这个异常表示session已经关闭,很多情况下我们在关闭了session再进行saveOrUpdate,save等跟持久化相关的操作都会报类似的异常。
 Hibernate3考虑到了我们这个需求,它实现了一个DetachedCriteria,这个可以独立于Session而存在。
 我们来看一下例子:(实体还是上面的)

public static void main(String[] args) { 

    Configuration cfg = new Configuration().configure();
    SessionFactory sessionFactory = cfg.buildSessionFactory();
    Session session = sessionFactory.openSession(); 

    DetachedCriteria decriteria = DetachedCriteria.forClass(User.class);
    decriteria.add(Restrictions.eq("name","shun")); 

    List list = decriteria.getExecutableCriteria(session).list();
    Iterator iter = list.iterator();
    while(iter.hasNext()) {
      User user = (User)iter.next();
      System.out.println(user.getName()+":"+user.getAge());
    } 

    session.close(); 

    Session session2 = sessionFactory.openSession();
    List list2 = decriteria.getExecutableCriteria(session2).list();
    Iterator iter2 = list2.iterator();
    while(iter2.hasNext()) {
      User user = (User)iter2.next();
      System.out.println(user.getName()+":"+user.getAge());
    }
  }

我们看到在session关闭之后,我们在另外一个连接中还是可以继续用DetachedCriteria。我们需要通过getExecutableCriteria(Session session)把当前的DetachedCriteria跟某一个Session进行关联。
 
 
 接下来我们再来看一下Subqueries类与DetachedCriteria的结合使用:

public static void main(String[] args) { 

    Configuration cfg = new Configuration().configure();
    SessionFactory sessionFactory = cfg.buildSessionFactory();
    Session session = sessionFactory.openSession(); 

    DetachedCriteria decriteria = DetachedCriteria.forClass(User.class);
    decriteria.setProjection(Projections.avg("age")); 

    Criteria criteria = session.createCriteria(User.class);
    criteria.add(Subqueries.propertyGt("age",decriteria));
    List list = criteria.list();
    Iterator iter = list.iterator();
    while(iter.hasNext()) {
      User user = (User)iter.next();
      System.out.println(user.getName()+":"+user.getAge());
    } 

    session.close(); 

  }

估计大家有疑问的应该是第一句代码:

decriteria.setProjection(Projections.avg("age"));

这句代码是指通过decriteria得到age的平均值。然后在下面取得大于平均值的age的对象。
 Projections包含了许多实现SQL方法的封装方法,大家可以看一下API。

下面我们来了解一下它的稍微高级点的用法。
 直接看代码吧:

criteria.setFirstResult(10);
criteria.setMaxResults(20);

这里我们设置了开始的记录是第10条,然后从第10条开始查出20条记录,根据这个做法,我们就可以实现基本的分页功能了。
 当然,我们在很多情况下都需要排序,criteria也是支持的:

 criteria.addOrder(Order.desc("age"));

这里,我们直接用addOrder方法即可,里面通过Order.desc得到一个Order对象,它需要一个属性参数。实际上当我们调用addOrder时,hibernate会帮我们生成order by age,这样的语句。
 
 当我们需要进行分组时,这个怎么做呢?这个就需要用到我们上次有涉及到的Projections这个类的groupProperty方法,

criteria.setProjection(Projections.groupProperty("age"));

这里我们就根据age属性来进行分组,实际上也就是通过age对应的字段age进行分组,hibernate会自动帮我们转换成group by age这样的语句。
Projections中有许多实用的方法(注意,此为是hibernate 3后才有的)。

(0)

相关推荐

  • 在Java的Hibernate框架中对数据库数据进行查询操作

    Hibernate查询语言(HQL)是一种面向对象的查询语言,类似于SQL,但不是对表和列操作,HQL适用于持久对象和它们的属性. HQL查询由Hibernate转换成传统的SQL查询,这在圈上的数据库执行操作. 虽然可以直接使用SQL语句和Hibernate使用原生SQL,但建议使用HQL尽可能避免数据库可移植性的麻烦,并采取Hibernate的SQL生成和缓存策略的优势. 都像SELECT,FROM和WHERE等关键字不区分大小写,但如表名和列名的属性是区分在HQL敏感. FROM 语句 使

  • Hibernate 查询方式总结

    1. get() and load() Java代码 session.get(Clazz, id); session.load(Clazz, id); session.get(Clazz, id); session.load(Clazz, id); 说明: load()与get()的区别 请注意如果没有匹配的数据库记录,load()方法可能抛出无法恢复的异常(unrecoverable exception). 如果类的映射使用了代理(proxy),load()方法会返回一个未初始化的代理,直到你

  • Hibernate中的多表查询及抓取策略

    1.Hibernate中的多表查询  1.1SQL中的多表查询 [交叉连接] select * from A,B; [内连接] 显示内连接:inner join(inner 可以省略) Select * from A inner join B on 条件; 隐式内连接: Select * from A,B where 条件; [外连接] 左外连接:left outer join Select * from A left outer join B on 条件; 右外连接:right outer j

  • hibernate 命名查询如何实现

    什么是命名查询? Hibernate允许在映射文件中定义字符串形式的查询语句,这种查询方式成为命名查询 使用命名查询有什么好处? 由于使用Hibernate的HQL常常需要在Java代码中写字符串查询语句,HQL混杂在代码之间,破坏代码可读性,通过使用命名查询,可以使业务逻辑和查询语句分离,使您专注于查询,而避免了 SQL 或者 HQL 代码分散于整个应用程序中的情况. 可以应用命名查询做复杂查询的处理 命名查询如何实现? 介绍下面几种方式: 方法一:在配置文件中<class/>标记的下面,声

  • 全面解析Hibernate关联操作、查询操作、高级特性、并发处理机制

    本文所需的数据库初始文件,Hibernate常用操作的完整示例代码(包含所有Hibernate操作所需jar文件)提供下载学习:http://download.csdn.net/detail/daijin888888/9551724 1.Hibernate关联映射   1)什么是关联映射? 如果表之间具有关联关系,Hibernate允许我们在hbm.xml中描述他们的关联关系,然后在我们操作其中一张表时,自动的根据这种关系操作到另外的关系表,那么这种关联关系的设置,我们称之为关联映射.     

  • springmvc4+hibernate4分页查询功能实现

    Springmvc+hibernate成为现在很多人用的框架整合,最近自己也在学习摸索,由于我们在开发项目中很多项目都用到列表分页功能,在此参考网上一些资料,以springmvc4+hibnerate4边学边总结,得出分页功能代码,虽然不一定通用,对于初学者来说有参考价值. 分页实现的基本过程: 一.分页工具类 思路: 1.编写Page类,定义属性,应该包括:查询结果集合.查询记录总数.每页显示记录数.当前第几页等属性. 2.编写Page类,定义方法,应该包括:总页数.当前页开始记录.首页.下一

  • Java的Hibernate框架数据库操作中锁的使用和查询类型

     Hibernate与数据库锁 一.为什么要使用锁? 要想弄清楚锁机制存在的原因,首先要了解事务的概念. 事务是对数据库一系列相关的操作,它必须具备ACID特征: A(原子性):要么全部成功,要么全部撤销. C(一致性):要保持数据库的一致性. I(隔离性):不同事务操作相同数据时,要有各自的数据空间. D(持久性):一旦事务成功结束,它对数据库所做的更新必须永久保持. 我们常用的关系型数据库RDBMS实现了事务的这些特性.其中,原子性. 一致性和持久性都是采用日志来保证的.而隔离性就是由今天我

  • Java Hibernate中使用HQL语句进行数据库查询的要点解析

    一.实体对象查询 实体对象查询是hql查询的基础,作为一种对象查询语言,在查询操作时和sql不同,查询字符串中的内容要使用类名和类的属性名来代替.这种查询方法相对简单,只要有SQL功底,使用hql是很简单的,但是有一些问题需要注意,就是查询获取数据不是目的,需要考虑的是如何编写出高效的查询语句,这才是讨论的重点. 1.N+1问题 (1)什么是N+1问题 在刚听到这个名词时疑惑可能是有的,以前根本就没有听过N+1问题,那么它是指什么呢?N+1指的是一张表中有N条数据,那么在获取这N条数据时会产生N

  • Java的Hibernate框架中Criteria查询使用的实例讲解

    我们讲一下Criteria查询,这个对于不是太熟悉SQL语句的我们这些程序员来说是很容易上手的.  废话不多说,看一下例子:  实体类如下: public class User implements Serializable{ private static final long serialVersionUID = 1L; public Long id; private String name; private int age; //省略Get/Set方法 } 映射文件我们就不写了,很简单的一个

  • 深入解析Java的Hibernate框架中的持久对象

    一.持久对象生命周期 应用程序在使用Hibernate框架后,创建的持久对象会经历一整套生命周期来完成数据库的操作,其中主要的三个状态分别是瞬态(Transient).持久化(Persistent).脱管(detached).这三种状态的转换是能够在应用程序中控制的,如下图: 为了能清楚的了解这几种状态,这里使用一个实例来查看下这几种状态下对象的不同,下面状态内的代码,具体步骤如下: (1)创建Hibernate_session程序集,并添加像相应的jar包: (2)配置Hibernate,添加

  • Java的Hibernate框架中用于操作数据库的HQL语句讲解

    上次我们一起学习了用Criteria进行相关的操作,但由于Criteria并不是Hibernate官方推荐的查询方式,我们也并不多用.现在我们来看一下官方推荐的HQL,一起学习一下它的强大.  说是HQL,也就是Hibernate查询语句,和SQL有什么区别呢?一个字母的区别,哈哈.  当然不是这样,HQL和SQL的区别在于思想的不同,HQL是用面向对象的方向进行查询,而SQL则是对数据库二维表进行查询,这里包含的是思想的不同.HQL实际上也是SQL,它由Hibernate帮我们在内部进行转换,

  • 详解Java的Hibernate框架中的缓存与原生SQL语句的使用

    Hibernate缓存 缓存是所有关于应用程序的性能优化和它位于应用程序和数据库之间,以避免数据库访问多次,让性能关键型应用程序有更好的表现. 缓存对Hibernate很重要,它采用了多级缓存方案下文所述: 第一级缓存: 第一级缓存是Session的缓存,是一个强制性的缓存,通过它所有的请求都必须通过. Session对象不断自身的动力的对象,提交到数据库之前. 如果发出多个更新一个对象,Hibernate试图拖延尽可能长的时间做了更新,以减少发出的更新SQL语句的数量.如果您关闭会话,所有被缓

  • 详解Java的Hibernate框架中的注解与缓存

    注解 Hibernate注解是一个没有使用XML文件来定义映射的最新方法.可以在除或替换的XML映射元数据使用注解. Hibernate的注解是强大的方式来提供元数据对象和关系表的映射.所有的元数据被杵到一起的代码POJO java文件这可以帮助用户在开发过程中同时要了解表的结构和POJO. 如果打算让应用程序移植到其他EJB3规范的ORM应用程序,必须使用注解来表示映射信息,但仍然如果想要更大的灵活性,那么应该使用基于XML的映射去. 环境设置Hibernate注释 首先,必须确保使用的是JD

  • Java的Hibernate框架中的组合映射学习教程

    一.组合映射 组合是关联关系的一种特殊情况,是关联关系耦合度最高的一种关系,组合的主对象和子对象拥有相同的生命周期,主对像消亡的话子对象也会消亡.这里使用雇主和用户作为示例,用户和雇主都拥有联系方式属性,如果这里站在对象角度思考的话,常常会把对象模型绘制成为组合的方式,抽象出来一个共同的联系方式类,然后两种人分别包含相应的联系方式对象即可,向应的对象模型时它的对象示例如下图所示: 组合对象模型在生成相应的关系模型后会把对应的子类包含到主表中,所以对应的表结构会将相应的属性生成到对应的表中,相应的

  • Java的Hibernate框架中的双向主键关联与双向外键关联

    一.双向主键关联 双向的主键关联其实是单向一对一主键关联的一种特殊情况,只不过要在关联对象的两端的映射文件中都要进行<one-to-one>的配置,另外还要在主映射的主键一端采用foreign外键关联属性. 这里同样使用Person和IdCard来讨论,一个人对应着一个唯一的身份证,而且一个身份证也唯一映射着一个人,所以这就产生了双向的关联关系,Person的主键同样也是IdCard的主键,分别是主键的同时也是外键,这种关联关系成为双向一对一映射,表现到关系模型中可如下图: 图中的两个表采用了

  • 详解Java的Hibernate框架中的缓存与二级缓存

    缓存 今天我们就来讲一下hibernate中实体状态和hibernate缓存.  1)首先我们先来看一下实体状态:  实体状态主要分三种:transient,persitent,detached.  看英文应该就大概明白了吧.  transient:是指数据还没跟数据库中的数据相对应.  persistent:是指数据跟数据库中的数据相对应,它的任何改变都会反映到数据库中.  detached:是指数据跟数据库中的数据相对应,但由于session被关闭,它所做的修改不会对数据库的记录造成影响.

  • 深入解析Java的Hibernate框架中的一对一关联映射

    作为一个ORM框架,hibernate肯定也需要满足我们实现表与表之间进行关联的需要.hibernate在关联方法的实现很简单.下面我们先来看看一对一的做法:  不多说了,我们直接上代码:  两个实体类,TUser和TPassport: public class TUser implements Serializable{ private static final long serialVersionUID = 1L; private int id; private int age; priva

随机推荐