hibernate查询之Criteria

前几次我们讲了hibernate的关联映射,映射完了我们就要开始来查询啦。

首先这一次我们讲一下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。

查询的我们先大概了解到这里,下次我们再一起学习一下分页的实现。

猜你喜欢

转载自cxshun.iteye.com/blog/1060497