Hibernate 的检索方式

在实际开发项目中,对数据进行最多的操作就是查询,数据的查询在所有 ORM 框架中都占有极其重要的地位。那么,如何利用 HIbernate 查询数据呢?接下学习Hibernate 的检索方式。

Hibernate 的检索方式主要有 5 种,分别为导航对象图检索方式、OID 检索方式、HQL 检索方式、QBC 检索方式和原生 SQL 检索方式。下面就对这 5 种检索方式一一向详解。

对象图导航检索

根据已经加载的对象,导航到它的关联对象。它利用类与类之间的关系来检索对象。

//由Linkman对象自动导航到来联系人所属的客户对象
LInkMan lk = (LinkMan)session.get(LinkMan.class,1l);
Customer c = lk.getCustomer();

当然,其前提是必须在对象关系映射文件上配置了多对一的关系

OID 检索

指用 Session 的 get() 和 load() 方法加载某条记录对应的对象。如下面两种加载客户对象的方式:

Customer c1 = session.get(Customer.class,1l);
Customer c2 = session.load(Customer.class,1l);

HQL 检索

HQL(Hibernate Query Language) 是面向对象的查询语言,它和 SQL 查询语言有些相似,但它使用的是类、对象和属性的概念,而没有表和字段的概念。在 HIbernate 提供的各种检索方式中,HQL 是官方推荐的查询语言,也是使用最广泛的一种检索方式

下面通过例子来学习 HQL 如何使用。。

基础语法
	// 基础语法
	@Test
	public void fun1() {

		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// ------------------------------------------------
		// 1.书写HQL语句
		// String hql = "from com.pngyul.domain.Customer";//完整语法
		String hql = "from Customer";// 简单写法
		// 2.根据SQL语句查询对象
		Query query = session.createQuery(hql);
		// 3.根据查询对象获得查询结果
		List<Customer> list = query.list();// 放回list结果
		// query.uniqueResult();//接受唯一的查询结构

		System.out.println(list);

		// ------------------------------------------------

		transaction.commit();
	}
排序检索
	// 排序
	@Test
	public void fun2() {

		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// ------------------------------------------------

		String hql = "from Customer order by cust_id asc ";//升序
		// String hql = "from Customer order by cust_id desc ";//降序

		Query query = session.createQuery(hql);

		List<Customer> list = query.list();

		System.out.println(list);

		// ------------------------------------------------

		transaction.commit();
	}
条件检索
	//条件
	@Test
	public void fun3() {

		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// ------------------------------------------------
		
		//String hql = "from Customer where cust_id = ?";// 条件查询--?占位符查询方式
		String hql = "from Customer where cust_id =:id ";// 条件查询--命名占位符查询

		Query query = session.createQuery(hql);
		
//		query.setParameter(0, 3l);
        query.setParameter("id", 3l);//设置参数

		Customer c = (Customer) query.uniqueResult();// 接受唯一的查询结构

		System.out.println(c);

		// ------------------------------------------------

		transaction.commit();
	}
分页检索
		// 分页
		@Test
		public void fun4() {

			Session session = HibernateUtils.getCurrentSession();
			Transaction transaction = session.beginTransaction();
			// ------------------------------------------------

			String hql = "from Customer";

			Query query = session.createQuery(hql);
			
			//limit ?,?
			query.setFirstResult(0);//设置其实索引
			query.setMaxResults(2);//取多少个
			
			List<Customer> list = query.list();

			System.out.println(list);

			// ------------------------------------------------

			transaction.commit();
		}
统计检索
		// 聚合
		@Test
		public void fun5() {

			Session session = HibernateUtils.getCurrentSession();
			Transaction transaction = session.beginTransaction();
			// ------------------------------------------------

//			String hql = "select count(*) from Customer";
//			String hql = "select sum(cust_id) from Customer";
//			String hql = "select avg(cust_id) from Customer";
//			String hql = "select max(cust_id) from Customer";
			String hql = "select min(cust_id) from Customer";//含有聚合函数的HQL
			
			Query query = session.createQuery(hql);

			Number number = (Number) query.uniqueResult();

			System.out.println(number);

			// ------------------------------------------------

			transaction.commit();
		}
投影查询
		// 投影查询
		@Test
		public void fun6() {

			Session session = HibernateUtils.getCurrentSession();
			Transaction transaction = session.beginTransaction();
			// ------------------------------------------------

			//String hql = "select cust_name from Customer";//返回一个List<String>
			//String hql = "select cust_id,cust_name from Customer";//返回List<Object[]>
			
			//前提:必须提供对应的构造方法,返回一个Customer对象
			String hql = "select new Customer(cust_id,cust_name) from Customer";
			
			Query query = session.createQuery(hql);

			List<Customer> list = query.list();

			System.out.println(list);

			// ------------------------------------------------

			transaction.commit();
		}
HQL 的多表查询
回顾-原生SQL
		交叉连接-笛卡尔积(避免)
		select * from A,B 
		内连接
				|-隐式内连接
				select * from A,B  where b.aid = a.id
				|-显式内连接
				select * from A inner join B on b.aid = a.id
		外连接
				|- 左外
				select * from A left [outer] join B on b.aid = a.id
				|- 右外
				select * from A right [outer] join B on b.aid = a.id

HIbernate 进行多表查询与 SQL 其实是很相似的,但是 HQL 会在原来 SQL 分类的基础上又多处一些操作。

HQL 的多表连接查询的分类如下:

交叉连接(避免用,没什么意义)
内连接
     隐式内连接
     显式内链接
     迫切内连接
外连接
 	左外连接(迫切)
 	右外连接(迫切)

内连接

	@Test
	public void fun1() {

		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// ------------------------------------------------
		//别问为什么,语法就是这样
		String hql = "from Customer c inner join c.linkMens" ;

		Query query = session.createQuery(hql);
		//返回一个List<Object[]>集合
		//每条记录返回的数据封装到Customer对象和LinkMan对象中
		//所以每条记录都会是装有两个对象的集合
		List<Object[]> list = query.list();

		for(Object[] arr : list){
			System.out.println(Arrays.toString(arr));
		}

		// ------------------------------------------------

		transaction.commit();
	}

迫切内连接

// 迫切内连接
	@Test
	public void fun2() {

		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// ------------------------------------------------
		//注意:该hql语句在inner join 后多了个关键字 fetch
		String hql = "from Customer c inner join fetch c.linkMens" ;

		Query query = session.createQuery(hql);
		//返回的式一个Cutomer 集合
		List<Customer> list = query.list();

        System.out.println(list);

		// ------------------------------------------------

		transaction.commit();
	}

我们测试发现,无论内连接还是迫切内连接打印出来的(发送的) SQL 语句都是一样的,而且在生成的 SQL 语句中也没有 fetch 关键字,当然 fetch 本身就不是 SQL 语句的关键字。所以 fetch 只能在 HQL 中使用,生成了 SQL 语句以后,fetch 就消失了。那么 fetch 到底有什么用呢?

他们之间的主要区别在于封装数据。虽然我们查询到的数据是一样的,但是 Hibernate 发现 HQL 中有 fetch 就会将数据封装到一个对象中,把属于客户的数据封装到 Customer 对象中,将属于联系人的部分封装到 Customer 中的联系人集合中,这样最后封装完成就是一个 List< Customer >中。而内连接时分别封装到两个对象中,返回 List<Object[]>.

左外连接

	// 左外连接
	@Test
	public void fun3() {

		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// ------------------------------------------------

		String hql = "from Customer c left join c.linkMens";

		Query query = session.createQuery(hql);

		List<Object[]> list = query.list();

		for (Object[] arr : list) {
			System.out.println(Arrays.toString(arr));
		}

		// ------------------------------------------------

		transaction.commit();
	}

右外连接

	// 右外连接
	@Test
	public void fun4() {

		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		// ------------------------------------------------

		String hql = "from Customer c right join c.linkMens";

		Query query = session.createQuery(hql);

		List<Object[]> list = query.list();

		for (Object[] arr : list) {
			System.out.println(Arrays.toString(arr));
		}

		// ------------------------------------------------

		transaction.commit();
	}

QBC 检索

QBC(Query By Criteria) 是 Hibernate 提供的另一种检索对象的方式,完全面向对象。

我们直接通过例子来学习,在例子中每一步我会附上注释,方便你们理解

基本检索
	// 基础语法
	@Test
	public void fun1() {

		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		//--------------------------------------------
		//Criteria时Hibernate提供的一个查询接口
		//获得 criteria 对象
		Criteria criteria = session.createCriteria(Customer.class);
		//执行查询,返回查询结果
		List<Customer> list = criteria.list();
		System.out.println(list);
		
		//--------------------------------------------
		transaction.commit();
	}
条件检索
	// 条件查询

	// > 			 gt
	// >=			 ge
	// <			 lt
	// <=		 	 le
	// == 			 eq
	// != 			 ne
	// in 		     in
	// between and   between
	// like 		 like
	// is not null   isNotNull
	// is null       isNull
	// or 			 or
	// and           and
	@Test
	public void fun2() {

		Session session = HibernateUtils.openSession();
		Transaction transaction = session.beginTransaction();

		// ---------------------------------
		// 创建criteria查询对象
		Criteria criteria = session.createCriteria(Customer.class);
		//Restrictions 提供了大量的静态方法来创建查询条件,查询条件方法名如上
		// 添加查询参数 => 查询cust_id为4的Customer对象
		criteria.add(Restrictions.eq("cust_id", 4l));
		// criteria.add(Restrictions.ne("cust_id", 3l));
		// criteria.add(Restrictions.between("cust_id", 3l, 4l));
		// criteria.add(Restrictions.like("cust_name", "%王%"));
		// criteria.add(Restrictions.isNotNull("cust_source"));
		// criteria.add(Restrictions.isNull("cust_source"));

		// 获得查询结果
		List<Customer> list = criteria.list();// 放回list结果
		// Customer c = (Customer) criteria.uniqueResult();//接受唯一的查询结构
		System.out.println(list);
		// ---------------------------------

		transaction.commit();
		session.close();

	}
分页检索
	// 分页 
	@Test
	public void fun3() {

		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		//--------------------------------------------
		
		Criteria criteria = session.createCriteria(Customer.class);
		
		//limit ?,?
		criteria.setFirstResult(0);
		criteria.setMaxResults(3);
		
		List<Customer> list = criteria.list();
		System.out.println(list);
		
		//--------------------------------------------
		transaction.commit();
	}
排序检索
	// 排序 
	@Test
	public void fun4() {

		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		//--------------------------------------------
		
		Criteria criteria = session.createCriteria(Customer.class);
		criteria.addOrder(Order.asc("cust_id"));//根据cust_id升序
		List<Customer> list = criteria.list();
		System.out.println(list);
		
		//--------------------------------------------
		transaction.commit();
	}
统计检索
	//统计 
	@Test
	public void fun5() {

		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		//--------------------------------------------
		
		Criteria criteria = session.createCriteria(Customer.class);
		//这个方法调用聚合函数
		criteria.setProjection(Projections.avg("cust_id"));
		
		double  avg = (double) criteria.uniqueResult();
		System.out.println(avg);
		
		//--------------------------------------------
		transaction.commit();
	}
离线条件查询

DetachedCriteria(离线条件查询),它可以脱离 Session 来使用的一种条件查询对象,我们都知道 Criteria 对象必须由 Session 对象来创建。那么也就是说必须先有 Session 才可以生成 Criteria 对象。而 DetachedCriteria 对象可以在其他层对条件进行封装。

这个对象很实用,它的主要有点是做一些特别复杂的条件查询的时候,往往会在 web 层向业务层传递很多参数,业务层又会将这些参数传递给 Dao 层。最后在 Dao 层中拼接 sql完成查询。有个离线条件查询对象后,那么这些工作都可以不用关心了,我们可以在 web层将数据封装好,在传递到业务层和 dao 层完成查询。
在这里插入图片描述
例如下来这个模拟的例子:

	@Test
	public void fun1() {

		//模拟web,service层
		DetachedCriteria dc = DetachedCriteria.forClass(Customer.class);
		dc.add(Restrictions.idEq(3l));//拼装条件,与普通Criteria一致
		
		Session session = HibernateUtils.getCurrentSession();
		Transaction transaction = session.beginTransaction();
		//获得与session关联的 Criteria
		Criteria criteria = dc.getExecutableCriteria(session);
		
		List list = criteria.list();
		System.out.println(list);
	}

原生 SQL 检索

	// 基本查询--返回对象List
	@Test
	public void fun2() {

		Session session = HibernateUtils.openSession();

		Transaction transaction = session.beginTransaction();

		// ---------------------------------
		// 查询所有的Customer对象
		// 1.书写sql语句
		String sql = "select * from cst_customer";
		// 2.创建sql查询对象
		SQLQuery query = session.createSQLQuery(sql);
		// 指定将哪个实体封装到对象中
		query.addEntity(Customer.class);
		//设置参数
		//query.setParameter(0, 1l);
		// 3.调用方法返回结果
		List<Customer> list = query.list();
		System.out.println(list);

		// ---------------------------------

		transaction.commit();
		session.close();
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值