九、Hibernate的多种查询方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/mChenys/article/details/84789038

一、唯一标识OID的检索方式

这种方式是通过主键来查找的,调用方式如session.get(对象.class,OID),适用于获取单条数据.

二、HQL的检索方式

什么是HQL
HQL(Hibernate Query Language) 是面向对象的查询语言, 它和 SQL 查询语言有些相似
在 Hibernate 提供的各种检索方式中, HQL 是使用最广的一种检索方式。

HQL与SQL的关系
HQL 查询语句是面向对象的,Hibernate负责解析HQL查询语句, 然后根据对象-关系映射文件中的映射信息, 把 HQL 查询语句翻译成相应的 SQL 语句。
HQL 查询语句中的主体是域模型中的类及类的属性。
SQL 查询语句是与关系数据库绑定在一起的,SQL查询语句中的主体是数据库表及表的字段。

注意:HQL语句的使用必须要开启事务,即调用createQuery方法必须要先开启事务,否则会报错:
org.hibernate.HibernateException: createQuery is not valid without active transaction
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:334)

HQL支持以下几种查询:
1.HQL基本的查询格式
支持方法链的编程,即直接调用list()方法,例如:
session.createQuery("from Customer").list();//from后面写的是类名而不是表名

2.使用别名的方式
session.createQuery("from Customer c").list();//as 可以省略
session.createQuery("select c from Customer c").list();

3.排序查询
排序查询和SQL语句中的排序的语法是一样的
session.createQuery("from Customer order by cust_id").list(); //升序,默认asc可省略
session.createQuery("from Customer order by cust_id desc").list(); //降序

4.分页查询
Hibernate框架提供了分页的方法,咱们可以调用方法来完成分页,两个方法如下
setFirstResult(index) //从哪条记录开始,如果查询是从第一条开启,从0开始,取值参考(pageNo-1)*pageSize
setMaxResults(pageSize) //每页查询的记录条数

例如获取第一页的数据,每页有10条数据,可以这样写:
List<LinkMan> list = session.createQuery("from LinkMan").setFirstResult(0).setMaxResults(10).list();

5.带条件的查询
有3种方式:

  • 按位置绑定参数的条件查询(指定下标值,默认从0开始)例如:
	...
	Query query = session.createQuery("from Linkman l where l.lkm_id >= ? and l.lkm_gender = ?");
	query.setLong(0, 2L);
	query.setString(1, "男");
	List<Linkman> list = query.list();
	...
  • 按名称绑定参数的条件查询(HQL语句中的 ? 号换成 :名称 的方式),例如:
	...
	Query query = session.createQuery("from Linkman l where l.lkm_id >= :id and l.lkm_gender = :sex");
	query.setLong("id", 2L);
	query.setString("sex", "男");
	List<Linkman> list = query.list();
	...
  • setParameter("?号的位置,默认从0开始",“参数的值”); 不用考虑参数的具体类型
    或者setParameter(“绑定的名称”,“参数的值”); 例如:
	...
	Query query = session.createQuery("from Linkman l where l.lkm_id >= ? and l.lkm_gender = :sex");
	query.setParameter(0, 2L);
	query.setParameter("sex", "男");
	List<Linkman> list = query.list();
	...

注意:条件查询中的模糊查询的%是写在参数设置的方法里的,例如:

	...
	Query query = session.createQuery("from Linkman l where l.lkm_name like ?");
	query.setParameter(0, "%o%"); //这里填写模糊查询的表达式
	List<Linkman> list = query.list();
	...

6.投影查询
投影查询就是想查询某一字段的值或者某几个字段的值.返回的结果有两种:

  • 返回数组的集合
	...
	Query query = session.createQuery("select lkm_name,lkm_gender from Linkman");
	List<Object[]> list = query.list();//返回的是数组的集合
	for (Object[] objects : list) {
		System.out.println(Arrays.toString(objects));
	}
	...

输出的结果:
在这里插入图片描述

  • 返回javabean集合
    必须在javabean中提供指定字段的构造方法,例如:
	public Linkman(String lkm_name, String lkm_gender) {
		this.lkm_name = lkm_name;
		this.lkm_gender = lkm_gender;
	}

	public Linkman() {
	}

然后HQL语句也要做相应变化,例如:

	...
	Query query = session.createQuery("select new Linkman(lkm_name,lkm_gender) from Linkman where lkm_gender=?");
	query.setParameter(0, "女");
	List<Linkman> list = query.list();// 返回的是对象的集合
	for (Linkman lm : list) {
		System.out.println(lm);
	}
	...

7.聚合函数查询
HQL语句还能使用count() sum() avg() max() min()等聚合函数,例如:

/**
	 * avg聚合函数查询
	 */
	@Test
	public void test10() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 用Number类型接收的好处是方便类型转换,lkm_id是Linkman 的属性,而不是表的字段
		List<Number> lis = session.createQuery("select avg(lkm_id) from Linkman ").list();
		System.out.println(lis.get(0).longValue());
		tr.commit();
	}
	
	/**
	 * max聚合函数查询
	 */
	@Test
	public void test9() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 用Number类型接收的好处是方便类型转换,lkm_id是Linkman 的属性,而不是表的字段
		List<Number> lis = session.createQuery("select max(lkm_id) from Linkman ").list();
		System.out.println(lis.get(0).intValue());
		tr.commit();
	}
	
	/**
	 * sum聚合函数查询
	 */
	@Test
	public void test8() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 用Number类型接收的好处是方便类型转换,lkm_id是Linkman 的属性,而不是表的字段
		List<Number> lis = session.createQuery("select sum(lkm_id) from Linkman ").list();
		System.out.println(lis.get(0).intValue());
		tr.commit();
	}
	/**
	 * count聚合函数查询
	 */
	@Test
	public void test7() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 用Number类型接收的好处是方便类型转换,lkm_id是Linkman 的属性,而不是表的字段
		List<Number> lis = session.createQuery("select count(*) from Linkman ").list();
		System.out.println(lis.get(0).intValue());
		tr.commit();
	}

三、QBC检索方式

QBC:Query By Criteria 按条件进行查询,非常适合用于条件查询,完全面向对象的方式调用

注意:使用qbc查询的前提也必须要开启事务,即调用createCriteria方法必须要先开启事务,否则回报如下错误:
org.hibernate.HibernateException: createCriteria is not valid without active transaction
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invo

QBC查询支持以下几种查询:
1.简单查询

/**
	 * QBC的基本入门查询
	 */
	@Test
	public void test1() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 创建QBC查询接口
		Criteria criteria = session.createCriteria(Customer.class);
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		tr.commit();
	}

2.排序查询
需要使用addOrder()的方法来设置参数,参数使用org.hibernate.criterion.Order对象的常量

/**
	 * QBC的排序查询
	 */
	@Test
	public void test2() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 创建QBC查询接口
		Criteria criteria = session.createCriteria(Customer.class);
		criteria.addOrder(Order.desc("cust_id"));//按照属性cust_id降序排序
		List<Customer> list = criteria.list();
		for (Customer customer : list) {
			System.out.println(customer);
		}
		tr.commit();
	}
	

3.分页查询
QBC分页的方法和HQL分页的方式一样的,操作的是setFirstResult();和setMaxResults();这2个方法

/**
	 * QBC的分页查询
	 */
	@Test
	public void test3() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		Criteria criteria = session.createCriteria(Linkman.class);
		// 设置分页查询从第一条记录开始(pageNo-1)*pageSize, 查询3条数据,调用方式可以链式调用
		List<Linkman> list = criteria.setFirstResult(0).setMaxResults(3).list();
		for (Linkman linkman : list) {
			System.out.println(linkman);
		}

		tr.commit();
	}

4.条件查询
Criterion是查询条件的接口,Restrictions类是Hibernate框架提供的工具类,使用该工具类来设置查询条件,条件查询使用Criteria接口的add方法来传入条件,有以下条件可传:

  • Restrictions.eq:相等
  • Restrictions.gt:大于号
  • Restrictions.ge:大于等于
  • Restrictions.lt:小于
  • Restrictions.le :小于等于
  • Restrictions.between:在之间
  • Restrictions.like:模糊查询
  • Restrictions.in :范围
  • Restrictions.and:并且
  • Restrictions.or:或者
  • Restrictions.isNull:空值查找

例如:

/**
	 * QBC的条件查询
	 */
	@Test
	public void test4() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		Criteria criteria = session.createCriteria(Linkman.class);
		//使用方法添加条件 
		criteria.add(Restrictions.eq("lkm_gender","男")); //等于男
		//lkm_id大于等于2,小于5
		criteria.add(Restrictions.and(Restrictions.ge("lkm_id",2L),Restrictions.lt("lkm_id",5L)));
		
		List<Linkman> list = criteria.list();
		for (Linkman linkman : list) {
			System.out.println(linkman);
		}
		tr.commit();
	}
/**
	 * QBC的条件查询之in查询
	 */
	@Test
	public void test5(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 创建QBC查询接口
		Criteria criteria = session.createCriteria(Linkman.class);
		
		// SQL:select * from cst_linkman where lkm_id in (1,2,5);
		List<Long> params = new ArrayList<Long>();
		params.add(1L);
		params.add(2L);
		params.add(5L);
		
		// 使用in 方法查询
		criteria.add(Restrictions.in("lkm_id", params));
		
		List<Linkman> list = criteria.list();
		for (Linkman linkman : list) {
			System.out.println(linkman);
		}
		tr.commit();
	}

5.聚合函数查询
Projection的聚合函数的接口,而Projections是Hibernate提供的工具类,使用该工具类设置聚合函数查询,常用的方法有:
在这里插入图片描述
例如:

/**
	 * QBC的聚合函数查询
	 */
	@Test
	public void test6(){
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 创建QBC查询接口
		Criteria criteria = session.createCriteria(Linkman.class);
		//聚合函数count使用
		criteria.setProjection(Projections.count("lkm_id"));
		
		List<Number> list= criteria.list();
		System.out.println(list.get(0).intValue());
		tr.commit();
	}
/**
	 * QBC的多次查询
	 */
	@Test
	public void test8() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 创建QBC查询接口
		Criteria criteria = session.createCriteria(Linkman.class);
		// 聚合函数count使用
		criteria.setProjection(Projections.count("lkm_id"));
		// 查询count
		List<Number> list = criteria.list();
		System.out.println(list.get(0).intValue());

		// 重置projection
		criteria.setProjection(null);
		List<Linkman> lms = criteria.list();

		for (Linkman lm : lms) {
			System.out.println(lm);
		}
		tr.commit();
	}

提示:criteria.setProjection(null);也是有意义的,它是用于重置聚合函数的查询条件,比如你想在一个方法里面重复是用criteria.list();去查询结果,由于第一次已经使用了聚合函数,第二次如果不想使用,可以直接调用criteria.setProjection(null);来重置.

四、离线条件查询

离线条件查询使用的是DetachedCriteria接口进行查询,离线条件查询对象在创建的时候,不需要使用Session对象,只是在查询的时候使用Session对象即可。通常在web层就可以设置好查询条件,然后传入到service层使用,创建DetachedCriteria方式例如:
DetachedCriteria criteria = DetachedCriteria.forClass(Linkman.class);
然后就可以调用add方法添加各种条件了或者setProjection添加聚合函数,例如:

/**
	 * 离线查询
	 */
	@Test
	public void test9() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 创建离线Criteria
		DetachedCriteria criteria = DetachedCriteria.forClass(Linkman.class);
		// 添加条件
		criteria.add(Restrictions.eq("lkm_gender", "女"));

		// 开始查询
		List<Linkman> list = criteria.getExecutableCriteria(session).list();
		for (Linkman linkman : list) {
			System.out.println(linkman);
		}
		tr.commit();
	}

五、SQL查询方式

如果喜欢手写sql语句的朋友,可以使用这种方式,通过session.createSQLQuery(sql语句);的方式来执行sql查询.例如:

/**
	 * 把数据封装到对象中
	 */
	@Test
	public void test2() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 创建的是SQL的查询的接口
		SQLQuery query = session.createSQLQuery("select * from cst_linkman where lkm_gender = ?");
		// 通过该方法关联实体类
		query.addEntity(Linkman.class);
		// 设置条件
		query.setParameter(0,"男");
		List<Linkman> list = query.list();
		for (Linkman linkman : list) {
			System.out.println(linkman);
		}

		tr.commit();
	}


	/**
	 * 测试SQL语句的查询,输出数组集合
	 */
	@Test
	public void test1() {
		Session session = HibernateUtils.getCurrentSession();
		Transaction tr = session.beginTransaction();
		// 创建的是SQL的查询的接口
		SQLQuery query = session.createSQLQuery("select * from cst_linkman");
		// 查询数据
		List<Object[]> list = query.list();
		for (Object[] objects : list) {
			System.out.println(Arrays.toString(objects));
		}

		tr.commit();

	}

猜你喜欢

转载自blog.csdn.net/mChenys/article/details/84789038