前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hibernate对象导航语言

Hibernate对象导航语言

作者头像
爱撒谎的男孩
发布2019-12-31 14:56:18
8650
发布2019-12-31 14:56:18
举报

文章目录

  1. 1. HQL - 对象导航语言
    1. 1.1. 简介
    2. 1.2. 步骤
    3. 1.3. 准备
    4. 1.4. 实体查询
      1. 1.4.1. 格式
      2. 1.4.2. 拓展
      3. 1.4.3. 实例
    5. 1.5. 部分字段的查询
      1. 1.5.1. 格式
      2. 1.5.2. 实例
    6. 1.6. 多表联合查询
    7. 1.7. 前提
      1. 1.7.1. 常见的联合查询方式
      2. 1.7.2. 对象方式关联查询
        1. 1.7.2.1. 实例
      3. 1.7.3. join方式查询
        1. 1.7.3.1. 左外连查询
          1. 1.7.3.1.1. 格式
          2. 1.7.3.1.2. 实例
        2. 1.7.3.2. 右外连接查询
          1. 1.7.3.2.1. 格式
          2. 1.7.3.2.2. 实例
        3. 1.7.3.3. 迫切左外连接
        4. 1.7.3.4. 迫切右外连接
        5. 1.7.3.5. select子句关联查询
          1. 1.7.3.5.1. 格式
          2. 1.7.3.5.2. 实例
    8. 1.8. 去除重复的数据
    9. 1.9. 聚合函数的查询
      1. 1.9.1. 常见的聚合函数
    10. 1.10. order by子句
    11. 1.11. group by 子句
    12. 1.12. 参考文章

HQL - 对象导航语言

简介

  • HQL(Hibernate Query Language) 是面向对象的查询语言, 它和 SQL 查询语言有些相似. 在 Hibernate 提供的各种检索方式中, HQL 是使用最广的一种检索方式. 它有如下功能:
    1. 在查询语句中设定各种查询条件;
    2. 支持投影查询, 即仅检索出对象的部分属性;
    3. 支持分页查询;
    4. 支持连接查询;
    5. 支持分组查询, 允许使用 HAVING 和 GROUP BY 关键字;
    6. 提供内置聚集函数, 如 sum(), min() 和 max();
    7. 支持子查询;
    8. 支持动态绑定参数;
    9. 能够调用 用户定义的 SQL 函数或标准的 SQL 函数。

步骤

  1. 获取Session对象
  2. 编写hql语句
  3. 使用session.createQuery(String hql)创建Query对象
  4. 使用session.setXX(index,Object)设置占位符的值
  5. 执行query.list()获取实体对象即可

准备

  • 创建Husband实体类
package cn.tedu.hibernate.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="husband")
public class Husband implements Serializable{
	private static final long serialVersionUID = 7403209578400736239L;
	private Integer id;
	private String name;
	private int age;
	private Wife wife;
	
	@Id
	@GeneratedValue   //主键自增长
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	
	@Column(length=10)
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	@OneToOne(fetch=FetchType.LAZY) 
	@JoinColumn(name="wife_id")   //设置外键名称为wife_id
	public Wife getWife() {
		return wife;
	}
	public void setWife(Wife wife) {
		this.wife = wife;
	}
	
	@Override
	public String toString() {
		return "Husband [id=" + id + ", name=" + name + ", age=" + age
				+ ", wife=" + wife + "]";
	}
}
  • 创建Wife的实体类
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="wife")
public class Wife implements Serializable {
	private static final long serialVersionUID = -7203920255946679244L;
	private Integer id;
	private String name;
	private int age;
	@Id
	@GeneratedValue
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	
	@Column(length=10)
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Wife [id=" + id + ", name=" + name + ", age=" + age + "]";
	}
}
  • 创建工具类,用来生成Session
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
	private static Configuration configuration;
	private static SessionFactory sessionFactory;
	/*
	 * 静态语句块中的内容只是在类加载的时候只创建一次,因此这里的大大减少了资源的消耗
	 */
	static {
		// 加载核心配置文件hibernate.cfg.xml
		configuration = new Configuration();
		configuration.configure();
		// 创建SessionFactotry对象
		sessionFactory = configuration.buildSessionFactory();
	}
	//创建session对象,在测试类中可以使用这个静态方法获取session
	public static Session getSession() {
		return sessionFactory.openSession();
	}
}

实体查询

  • 查询结果返回的是一个List<>的集合。其中的泛型为实体类
  • 相当于sql语句中的select * from husband;
  • 使用的hql语句是from Husband where id=?,这里还可以和sql语句一样使用别名来获取其中的值,比如: from Husband h where h.id=?

格式

  • from Husband where id=? ,其中的Husband是实体类的名字,而不是表的名称,后面的属性实体类中的属性名称,而不是表中字段的名称,区分大小写

拓展

  • where子句中只要是sql语句被能够满足的都是可以写的,比如=, , <, >, <=, >=, between, not between, in ,not in, is, like,同时也是可以写算术表达式
FROM User user WHERE user.age<20
FROM User user WHERE user.name IS null
FROM User user WHERE user.name LIKE 'Er%'
FROM User user WHERE (user.age % 2 = 1)
FROM User user WHERE (user.age<20) AND (user.name LIKE '%Er')

实例

  • 查询husband这张表,其中对应的实体类是Husband
@Test
	public void test1() {
		Session session = null;
		Transaction transaction = null;
		try {
			// 创建session
			session = HibernateUtil.getSession();
			// 开始事务
			transaction = session.beginTransaction();
            
			//编写hql语句
			String hql="from Husband where id=?";
            //String hql="from Husband h where h.id=?";
            
			//创建Query
			Query query=session.createQuery(hql);
			//设置占位符的值,这里的用法和PreparedStatement一样的用法
			query.setInteger(0,1);
			List<Husband> husbands=query.list();  //执行查询语句,返回的是list集合
			
			for (Husband husband : husbands) {
				System.out.println(husband);
			}
			
			// 提交事务
			transaction.commit();
		} catch (Exception exception) {
			transaction.rollback(); // 事务回滚
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

部分字段的查询

  • 实体对象的查询返回的是一个实体对象的List<>集合,我们这里需要查询的是表中的执行字段,而不是全部的字段

格式

  • select 实体类属性名 from 实体类名字 where 条件语句

实例

  • 查询出id=1的所有的husband中的name和age
    • sql语句:select name,age from husband where id=1
    • hql语句: select name,age from Husband h where h.id=?,此时的占位符id的值为1
  • 此时查询返回的结果List是一个Object[],其中的元素是nameage,并且是按照hql的语句的查询顺序存储的
//编写hql语句,只查询name和age属性字段
String hql="select name,age from Husband where id=?";
//创建Query
Query query=session.createQuery(hql);
//设置占位符的值,这里的用法和PreparedStatement一样的用法
query.setInteger(0,1);

//这里返回的是一个List集合,但是其中的每一个元素都是一个Object数组
List<Object[]> lists=query.list(); 
//遍历List集合
for (Object objects : lists) {
	//遍历数组,[0]的元素是name,[1]的元素是age
	for(int i=0;i<objects.length;i++){
		System.out.println(objects[i]);
	}
}
  • 这里查询的是两个字段,返回的结果List中存放的是Object[]但是如果我们查询的只有一个字段,那么返回的结果List中存放的是Object,这个值是你查询的字段的值

多表联合查询

前提

  • 必须存在关联关系,比如一对一,一对多,多对多

常见的联合查询方式

  1. 对象方式的关联查询
    1. 这个是HQL所特有的,因为这个需要用到对象之间的关系
  2. join方式关联
  3. select子句关联

对象方式关联查询

  • 假设我们需要查询wifeid值为1的husband表中指定的字段,我们除了使用多表联合查询,我们也可以使用关联查询,因为在Husband的实体类中有Wife这个对象
    • hql语句: select name,age from Husband h where h.wife.id=?
实例
//编写hql语句,where字句中的条件是wife的id
	String hql="select h.name,w.name from Husband h,Wife w where h.wife.id=? ";
	//创建Query
	Query query=session.createQuery(hql);
	//设置占位符的值,这里的用法和PreparedStatement一样的用法
	query.setInteger(0,1);
	
	List<Object> lists=query.list();
	
	//遍历查询结果
	for (Object object : lists) {
		Object[] objects=(Object[])object;
		for (int i = 0; i < objects.length; i++) {
			System.out.println(objects[i]);
		}
	}

join方式查询

左外连查询
  • 这个是等值连接的一种,即使两张表中的某一条数据不存在关联关系,那么也会全部查询出左边的那张表的全部数据
  • sql语句:select * from husband h left join wife w on h.wife_id=w.id,查询丈夫的所有数据并且和其对应妻子的信息,其中husbandwife这两张表是通过wife_id这个外键关联的
  • hql语句: select h.name,h.age,w.name,w.age from Husband h left join h.wife w,这条语句和上面的sql语句是一样的功能
格式
  • select 实体类属性 from 实体类名 [as] 别名 left join 别名.关联对象名 [as] 别名
    • 其中的as可以省略
    • 如果不需要查询关联对象的属性,那么后面的别名可以省略
    • left join后面跟的是实体类的关联对象,比如Husband中的Wife对象h.wife,这里就相当sql中的on h.wife_id=w.id
实例
  • 查询所有丈夫的信息和其对应的妻子的所有信息
  • hql: from Husband h left join h.wife,虽然这里的使用的是实体查询的方式,但是返回的却是Object[],其中的第一个元素是Husband对象,第二个是Wife对象
//编写hql语句
String hql="from Husband h left join h.wife";
//创建Query
Query query=session.createQuery(hql);

//执行查询,这里返回的是一个Object数组,其中数组的第一个元素是husband的数据,第二个是wife的数据
List<Object[]> list=query.list();
for (Object[] objects : list) {
	Husband husband=(Husband) objects[0];  //获取Husband对象
	Wife wife=(Wife)objects[1];  //获取Wife对象
}
  • 查询所有的丈夫信息和起对应的妻子的所有信息,这个和上面的例子一样,只不过是另外一种hql语句方式
//编写hql语句
String hql="select h,w from Husband h left join h.wife w";
//创建Query
Query query=session.createQuery(hql);

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

for (Object[] objects : list) {
	Husband husband=(Husband) objects[0];  //获取Husband对象
	Wife wife=(Wife)objects[1];  //获取Wife对象
}
  • 查询所有丈夫的nameage和其对应的妻子的的nameage信息
//编写hql语句
String hql="select h.name,h.age,w.name,w.age from Husband h left join h.wife w";
//创建Query
Query query=session.createQuery(hql);

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

for (Object object : list) {
	Object[] objects=(Object[])object;
	for (int i = 0; i < objects.length; i++) {
		System.out.print(objects[i]+"\t");
	}
	System.out.println();
}
  • 查询丈夫的所有信息
右外连接查询
  • 右外链接查询和左外连接查询的方式是一样的,只是此时如果出现两条记录没有关联关系的话,那么保留的是右边的表中的数据,即是查询右边表的所有数据和其对应的左边表的数据
格式
  • select 实体类属性 from 实体类名 [as] 别名 right join 别名.关联对象名 [as] 别名
    • 其中的as可以省略
    • 如果不需要查询关联对象的属性,那么后面的别名可以省略
    • right join后面跟的是实体类的关联对象,比如Husband中的Wife对象h.wife,这里就相当sql中的on h.wife_id=w.id
实例
  • 查询所有妻子的信息和其对应的丈夫的信息: select h,w from Husband h right join h.wife w
迫切左外连接
迫切右外连接
select子句关联查询
格式
  • select 对象.属性名,.... from 类名
    • 其中的对象实体类中的对象属性,比如Husband类中的Wife对象
实例
  • select h.wife.name,h.wife.age,h.name from Husband h
//编写hql语句,where字句中的条件是wife的id
String hql="select h.wife.name,h.wife.age,h.name from Husband h";
//创建Query
Query query=session.createQuery(hql);
//设置占位符的值,这里的用法和PreparedStatement一样的用法

List<Object> lists=query.list();

//遍历查询结果
for (Object object : lists) {
	Object[] objects=(Object[])object;
	for (int i = 0; i < objects.length; i++) {
		System.out.println(objects[i]);
	}
}

去除重复的数据

  • sql语句一样,使用distinct即可
  • 比如: select distinct name,age from Husband where id=?

聚合函数的查询

  • hql语句和sql一样,都是可以使用聚集函数查询
  • select count(*) from Husband where id=? 根据id查询出对应的人数

常见的聚合函数

  • count(*): 计算数量
    • select count(*) from Husband where id=?
  • sum() :求和
    • select sum(age) from Husband h where h.wife.id=?
  • AVG(): 求平均值
    • select avg(age) from Husband where age>10
  • MAX(): 求最大值
    • select max(age) from Husband where age>10 and age<90
  • MIN(): 求最小值
    • select min(age) from Husband where age>10 and age<100

order by子句

  • from Husband where id=? order by name desc,age asc 按照姓名将序排列,年龄升序排列

group by 子句

  • hql中也是可以使用group by子句进行分组的,比如select count(*),sum(age),max(age) from Husband h where h.age>? group by h.name
  • 同时也是可以使用having子句进行聚合函数的条件过滤,比如select count(*),sum(age),max(age) from Husband h where h.age>? group by h.name having count(*)>?

参考文章

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-04-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • HQL - 对象导航语言
    • 简介
      • 步骤
        • 准备
          • 实体查询
            • 格式
            • 拓展
            • 实例
          • 部分字段的查询
            • 格式
            • 实例
          • 多表联合查询
            • 前提
              • 常见的联合查询方式
              • 对象方式关联查询
              • join方式查询
            • 去除重复的数据
              • 聚合函数的查询
                • 常见的聚合函数
              • order by子句
                • group by 子句
                  • 参考文章
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档