Hibernate学习详解(2: HQL实用技术

Hibernate学习详解(2: HQL实用技术

HQL语句

Hibernate 支持三种查询方式 : HQL查询 Criteria查询 原生SQL查询
HQL查询

是Hibernate查询语言(Hibernate Query Language) 一种面向对象的查询语言, 与SQL(结构化查询语言不同)
其中没有表 和 字段的概念, 只有对象和属性的概念; (本次学习方向)
HQL语句形式上和SQL语句相似, 但又有不同…HQL是面向对象的可以理解为多态, 继承 关联…

Criteria查询 采用面向对象的方式构造查询;
原生SQL查询 直接执行SQL语句的查询,可以在SQL语句中根据不同的数据库进行特殊对应查询 ( 函数 序列等…)

常用HQL

注意:
	HQL语句对: Java类和属性区分大小写..!!  对其它大小写不影响;
	
因为:Hibernate中, 对每一个Java实体类已经在数据库中对应了数据库的一个表...
使用HQL查询时, 只需要使用对应的Java类,就相当于是对表的操作.... 

类名相当于表名 类中属性对应表中的列
From
from查询全部: 相当于查询, 该Java类对应的表的所有数据!! as 或 空格 起别名;
from Java类名
from Java类名 as 别名
from Java类名 别名


Select
select 用于选取查询对应的列:select 比较特殊后面讲解~
select 属性 from 类名;
select 别名.属性1,别名,属性2 from 类名 别名;


where
where子句用于表达式查询的限制条件: 根据条件查询, 或 非空条件;
from 类名 where 属性 = “”;
from 类名 where 属性 is not null;


表达式
表达式一般使用在where 子句中…
from 类名 where lower(字符类型属性)=“sadasd”; lower()表示匹配改列属性不区分大小写…
form 类名 where year(时间类型属性)=“1999”; year()取出时间类型的年份进行比较; 还有很多需要善于学习…


order by子句
order by用于按指定属性(列) 进行排序
from 类名 order by 属性 desc|asc

指向HQL

执行HQL语句的步骤

获取Session对象
编写 HQL语句
创建Query对象
执行查询,得到查询结果: Hibernate中提供两种方式都是Query对象的 list() 和 iterate();

关键代码: 实例Demo> hibernate实现增删改查续写
DeptDao.java

扫描二维码关注公众号,回复: 12273693 查看本文章
//list方法
	public void queryList(){
    
    
		//获取Session对象
		Session session = hibernateUtil.openSession();
		//编写 HQL语句
		String hql = "from Dept";
		//创建Query对象
		Query query = session.createQuery(hql);
		//执行查询,得到查询结果: Hibernate中提供两种方式都是Query对象的 list() 和 iterate();
		List<Dept> list = query.list();
		//关闭资源
		hibernateUtil.closeSessionn(session);
		//遍历结果
		for (Dept dept : list) {
    
    
			System.out.println(dept);
		}
	}

//iterate方法
	public void queryiterate(){
    
    
		//获取Session对象
		Session session = hibernateUtil.openSession();
		//编写 HQL语句
		String hql = "from Dept";
		//创建Query对象
		Query query = session.createQuery(hql);
		//执行查询,得到查询结果: Hibernate中提供两种方式都是Query对象的 list() 和 iterate();
		Iterator<Dept> Iterator = query.iterate(); 
		//遍历iterate 迭代器;
		while(Iterator.hasNext()){
    
    			
			Dept dept = Iterator.next();
			System.out.println(dept);
		}
		//关闭资源: iterate()属于懒加载最后关闭!! 
		hibernateUtil.closeSessionn(session);
	}
//自主在Test.java类中测试

list() 和 iterate() 区别:

都是hibernate 的实现查询方法, 根据 From 类名;返回对应的泛型类型;
list() 返回list<> 集合;
iterate() 返回 Iterator<> 迭代器; (需要对迭代器有一部分了解~)
iterate() 属于懒加载, 且iterate() 的查询方式与 list() 不同.
list() 一次性执行Hql 结果集存储在list()中;查询一次;
iterate() 会先从数据库获取到对应的主键值,在根据主键一条一条的查询对应的数据!! 查询多次
iterate() 优点,会缓存数据, 所以不建议一次的使用,对于经常查询的数据可以考虑iterate()…

在HQL语句中绑定参数

哈哈, 对于参数你们怎么像呢?
在HQL 中拼接参数吗?

	public void CS(String name){
    
    
		//省略...
		String hql = "from Dept where dname='"+name+"'";
		//省略...
	}

的确可行, 但并不好 性能低, 且不安全, 考虑SQL注入… 解决方案↓↓↓↓

Hibernate 中提供两种方式参数绑定 使用占位符
按参数位置绑定
按参数名称绑定
DeptDao.java

//根据dname 查询();
	public void query(String dname) {
    
    
		Session session = hibernateUtil.openSession();
		//定义hql
		//String hql = "from Dept where dname like ?";		//	?占位符
		String hql = "from Dept where dname like :dname";	//	起别名形式
		
		Query query = session.createQuery(hql);
		
		//query.setString(0,dname);						 //	?占位符: 	setxxx(int,xxx类型);		int对于占位符的下标 0开始,Obejct对应的值;
		query.setString("dname", "%"+dname+"%");		//	起别名形式:  setxxx(String,xxx类型);	String对应的别名,Objetc对应的值;
		
		List<Dept> list = query.list();
		hibernateUtil.closeSessionn(session);
		for (Dept dept : list) {
    
    
			System.out.println(dept);
		}
	}

//对于多个参数还可以使用Object[] 来进行处理...
	public void queryall(Object[] ob) {
    
    
		Session session = hibernateUtil.openSession();
		//定义hql
		String hql = "from Dept where dname like ? and loc like ?";		//	?占位符
		Query query = session.createQuery(hql);
		//通过遍历Object[] 集合数组形式来完成占位符的赋值...
		if(ob!=null && ob.length>0){
    
    
			for (int i = 0; i < ob.length; i++) {
    
    
				query.setParameter(i,ob[i]);		//根据数组下标,0开始,且Object可以是所有类型; 
			}
			//setParameter(int,Object);	 根据占位符下标.完成占位符赋值..
		}
		List<Dept> list = query.list();
		hibernateUtil.closeSessionn(session);
		//遍历结果...
		for (Dept dept : list) {
    
    
			System.out.println(dept);
		}
	}
//setParameter(int,Object); 	可以通过下标来给占位符赋值;
//setParameter(String,Object);	其实也有根据别名来完成赋值的方法,但是并不是很方便遍历(别名和值两个数组进行遍历..)...而Hibernate有更好的方法: setProperties(Object);
	public void queryPoroerties(Dept dept){
    
    
		Session session = hibernateUtil.openSession();
		//定义hql
		String hql = "from Dept where dname like :dname";	//使用别名进行赋值,这里使用对象所以 别名必须要和类的属性名对应!!
		Query query = session.createQuery(hql);
		//setProperties(类对象类型); 
		query.setProperties(dept);							//使用对象直接进行赋值...注意hql别名要和属性名对应!
		
		List<Dept> list = query.list();
		hibernateUtil.closeSessionn(session);
		for (Dept d : list) {
    
    
			System.out.println(d);
		}
	}

Test.java

		DeptDao ddDao = new DeptDao();
//		ddDao.query("");

//		Object[] ob = new Object[2];
//		ob[0]="%%";			//因为数值太少就啥也不填了,模糊查询直接写%号
//		ob[1]="%%";		
//		ddDao.queryall(ob);
		
		Dept dept = new Dept();
		dept.setDname("%%");
		ddDao.queryPoroerties(dept);

Hibernate 中提供两种方式参数绑定: 按参数位置绑定 按参数名称绑定
setXXX():针对具体数据类型
setXXX( int position, XXX类型 value); 为 ?占位符下标进行赋值…
setXXX( int position, XXX类型 value); 为指定 别名, 进行赋值…
setParameter():任意类型参数
setParameter( int position, Object value); 为 ?占位符下标进行赋值…可以将值定成一个Object[] 进行遍历…
setParameter( String name, Object value); 为指定 别名, 进行赋值… 不是很方便遍历Hibernate提供方法: setProperties(Object);
setProperties():专为命名参数定制
setProperties(Obeject); 参数是一个对象类型,使用时以对象的属性名 当作 别名进行赋值运行…
setProperties(Map); Map 以键值对形式, 键当作别名参数与Hql执行…
…还有很多善于发现

实现动态查询

动态SQL
以前学习 Mybatis时候了解过,根据提供的条件判断而产生不同的SQL语句执行出不同的结果;
对程序有一定的优化~通用性高…
Hibernate 中可以实现动态SQL

DeptDao.java

//动态sql
//根据输入的dname模糊查询如果没输入就查全部	
	public void queryD(Dept dept){
    
    
		Session session = hibernateUtil.openSession();
		String hql = "from Dept where 1=1";		// where 1=1方便后面拼接条件的 and/or;
		//动态条件判断
		if(dept.getDname()!=null && dept.getDname().length()>0){
    
    
			hql+=" and dname like :dname";	//空一格 拼接小细节~ dname注意对象中要存在对应属性名哦~
		}
		//将拼接好的 HQL进行执行;
		Query query = session.createQuery(hql);
		query.setProperties(dept);	//直接进行赋值...
		
		List<Dept> list = query.list();
		hibernateUtil.closeSessionn(session);
		for (Dept d : list) {
    
    
			System.out.println(d);
		}
	}	

Test.java

		Dept dept = new Dept();
		dept.setDname("%人%");
		ddDao.queryD(dept);

虽说上面实例很鸡肋! 但大概原来如此…

Query接口方法uniqueResult() 唯一结果 及 分页;

使用uniqueResult();获得唯一结果:

相比于 list iterate 都是返回的集合类型;而对于只返回一条的数据返回集合 并不适合;
*uniqueResult(); 返回值 Object类型;
对于只返回一条的记录可以使用… 在进行对于的强制类型转换. 相比返回集合该方法更适合!

DeptDao.java

	public void queryUnique(){
    
    
		Session session = hibernateUtil.openSession();
		String hql = "select count(*) from Dept";
		Query query = session.createQuery(hql);
		Long count = (Long)query.uniqueResult();
		hibernateUtil.closeSessionn(session);
		System.out.println("总共"+count+"条数据");
	}

分页

在之前学习过程中:
分页需要使用复杂的 SQL语句实现, 最关键的是对于不同数据库的分页方式又不同;
Mysql的 limit SqlServer的 top Oracle的rownum
Hibernate中提供:
setFirstResult() :设置从第几条开始
setMaxResults():设置读取最大记录数
有点类似于 mysql的limit …

DeptDao.java

//模拟分页
	public  void queryPage(Integer dye,Integer hang){
    
    	//dye当前页   hang每页行数;
		Session session = hibernateUtil.openSession();
		String hql = "from Dept";
		Query query = session.createQuery(hql);
		//对于分页,以下代码应该都了解不详细介绍了...
		//设置结果集中的起始位置
		query.setFirstResult((dye-1)*hang);
		//设置所需的数据数;
		query.setMaxResults(hang);			//如果不指定所需行数则是后面所有数据....
	
		List<Dept> depts = query.list();
		hibernateUtil.closeSessionn(session);
		//遍历集合..
		for (Dept dept : depts) {
    
    
			System.out.println(dept);
		}
	} 
	

Test.java

ddDao.queryPage(1,2);		//单纯调用方法();

使用投影

有时候数据展示, 并不需要对象的全部属性, 而是只需要对象中的某一个或几个属性;
又或要通过表达式,聚合函数 得到某些结果…可以使用投影
投影使用的是HQL的Select语句而不是 from 对于投影,查询结果将会有三种情况;

DeptDao.java

/*投影
 * 	当查询结果仅包含一个结果列,每个结果将作为一个Object的对象返回;
 * 	当查询结果不止一个结果列	,每个结果将作为一个Object[]的数组返回;
 * 	还可以使用 类的构造函数	,类确定每次返回的对象类型;
 * */
	public void query1() {
    
    
		Session session = hibernateUtil.openSession();
		String hql = "select dname from Dept";				//查询Dept2表的所有dname名;
		Query query = session.createQuery(hql);
		//因为返回只有一个列Object类型,定义为 String字符类型可以代表很多...
		List<String> list = query.list();	
		hibernateUtil.closeSessionn(session);
		//遍历
		for (String string : list) {
    
    
			System.out.println(string);
		}
	}

	public void query2() {
    
    
		Session session = hibernateUtil.openSession();
		String hql = "select dname,loc from Dept";				//查询Dept2表的所有dname名 和 loc ;
		Query query = session.createQuery(hql);
		//因为返回有多个列Object[]类型;
		List<Object[]> list = query.list();	
		hibernateUtil.closeSessionn(session);
		//遍历
		for (Object[] objects : list) {
    
    
			System.out.println(objects[0]+""+objects[1]);
		}
	}

	public void query3() {
    
    
		Session session = hibernateUtil.openSession();
		String hql = "select new Dept(dname,loc) from Dept";	//根据类的构造函数进行返回对应类型对象;	
		Query query = session.createQuery(hql);
		//使用类的构造进行查询,将返会的是 对应类型的集合...
		List<Dept> list = query.list();	
		hibernateUtil.closeSessionn(session);
		//遍历
		for (Dept dept : list) {
    
    
			System.err.println(dept);
		}
	}

Test.java

//调用各个查询语句;
		ddDao.query1();
		ddDao.query2();
		ddDao.query3();

注意别忘了实体类还需要的有参构造 **Dept.java**

	//为投影查询,返回对象类型提供的有参构造
	public Dept(String dname, String loc) {
    
    
		super();
		this.dname = dname;
		this.loc = loc;
	}

猜你喜欢

转载自blog.csdn.net/qq_45542380/article/details/109352461