配色: 字号:
Hibernate —— HQL、QBC检索方式
2017-01-13 | 阅:  转:  |  分享 
  
Hibernate——HQL、QBC检索方式



一、HQL检索方式



以双向的一对多来测试HQL检索方式。以Department和Employee为例。



建表语句:



CREATETABLEdepartment

(

dept_idINT(11)PRIMARYKEYNOTNULLAUTO_INCREMENT,

dept_nameVARCHAR(50)

);

CREATEINDEXFK_8hf3vewo7w3v9doungcc51wwyONdepartment(dept_id);

复制代码

CREATETABLEemployee

(

emp_idINT(11)PRIMARYKEYNOTNULLAUTO_INCREMENT,

emp_nameVARCHAR(50),

salaryFLOAT,

dept_id_fkINT(11),

CONSTRAINTFK_miun1wlqp4ujpsgfshyfi7g9jFOREIGNKEY(dept_id_fk)REFERENCESdepartment(dept_id)

);

CREATEINDEXFK_miun1wlqp4ujpsgfshyfi7g9jONemployee(dept_id_fk);

复制代码

对应的实体和hbm文件



publicclassDepartment{

privateIntegerdeptId;

privateStringdeptName;

privateSetemps=newHashSet<>();

}

publicclassEmployee{

privateIntegerempId;

privateStringempName;

privateFloatsalary;

privateDepartmentdept;

}

Department.hbm.xml

Employee.hbm.xml

1.在查询语句中设定各种查询条件



复制代码

@Test

publicvoidtestHql(){

Departmentdept=newDepartment();

dept.setDeptId(7);



Listlist=session.createQuery("FROMEmployeeewheree.empNamelike?ande.empId>?anddept=?orderbye.empId"+

"desc")

.setString(0,"%b%").setInteger(1,3).setEntity(2,dept).list();



for(Employeeemployee:list){

System.out.println(employee);

}



}

复制代码

说明:



(1)通过Session的createQuery(hql)方法创建一个Query对象,hql支持动态绑定参数。调用Query的相关方法执行查询。



(2)Query接口支持链式操作,它的setXxx()方法返回自身实例。



(3)方法setEntity(obj),obj只需要绑定一个id就可以。



(4)支持orderby排序。



(5)参数的位置从0开始。



复制代码

@Test

publicvoidtestHqlNamed(){

Listlist=session.createQuery("fromEmployeeewheree.empNamelike:nameande.empId>:idande.dept=?")

.setString("name","%a%").setInteger("id",1).list();

for(Employeeemployee:list){

System.out.println(employee);

}

}

复制代码

说明:



(1)支持按照参数名字查询,定义的参数名以":"开头。



2.查询对象的部分属性(查询结果仅包含实体的部分属性)



复制代码

@Test

publicvoidtestPropertyQuery(){

Departmentdept=newDepartment();

dept.setDeptId(7);

Listlist=session.createQuery("selectempName,empIdfromEmployeewheredept=?").setEntity(0,dept).list();

for(Object[]objects:list){

System.out.println(Arrays.asList(objects));

}

}

复制代码

说明:



(1)这种情况下查询出来的是一个Object[]数组类型。



复制代码

@Test

publicvoidtestPropertyQuery2(){

Departmentdept=newDepartment();

dept.setDeptId(7);

Listlist=session.createQuery("selectnewEmployee(empId,empName)fromEmployeewheredept=?").setEntity(0,dept)

.list();

for(Employeeemployee:list){

System.out.println(employee);

}

}

复制代码

(1)查询出来的是Employee类型



(2)需要在Employee实体类中定义相应的构造器,注意顺序。同时添加一个无参的构造器。



(3)可以通过Distinct关键字来去重。



3.分页查询



复制代码

@Test

publicvoidtestHqlPage(){

intpageNo=2;

intpageSize=3;



Listlist=session.createQuery("fromEmployee").setFirstResult((pageNo-1)pageSize).setMaxResults(pageSize).list();

for(Employeeemployee:list){

System.out.println(employee);

}



}

复制代码

(1)setFirstResult(intfirstResult):设定从哪一个对象开始检索。



(2)setMaxResults(intmaxResult):设定每次检索多少条记录。



4.命名查询(很少用到)



复制代码

@Test

publicvoidtestNamedQuery(){

intpageNo=3;

intpageSize=5;

Listemployees=session.getNamedQuery("findAllEmployees").setFirstResult((pageNo-1)pageSize).setMaxResults(

pageSize).list();

for(Employeeemployee:employees){

System.out.println(employee);

}

}

复制代码

说明:



(1)其中findAllEmployees定义在了Employee.hbm.xml文件中,用元素来定义,和class节点并列。



(2)通过Session的getNamedQuery()方法获取对应的Query对象。



5.聚集函数和分组查询



复制代码

@Test

publicvoidtestFunction(){

Listsalary=

session.createQuery("selectdept.deptName,min(salary),max(salary)fromEmployeegroupbydeptHAVINGmin(salary)>:salary")

.setFloat("salary",4000).list();

for(Object[]objects:salary){

System.out.println(Arrays.asList(objects));

}

}

复制代码

说明:



(1)通过GROUPBY进行分组,通过HAVING对分组数据设定约束条件。



(2)可以调用的聚集函数:count()、min()、max()、sum()、avg()



6.迫切左外链接和左外链接



(1)迫切左外链接



@Test

publicvoidtestHqlFetch(){

Listlist=session.createQuery("fromDepartmentdleftjoinfetchd.emps").list();

}

打印SQL:



复制代码

Hibernate:

select

department0_.dept_idasdept1_0_0_,

emps1_.emp_idasemp1_1_1_,

department0_.dept_nameasdept2_0_0_,

emps1_.emp_nameasemp2_1_1_,

emps1_.salaryassalary3_1_1_,

emps1_.dept_id_fkasdept4_1_1_,

emps1_.dept_id_fkasdept4_0_0__,

emps1_.emp_idasemp1_1_0__

from

hibernate.departmentdepartment0_

leftouterjoin

hibernate.employeeemps1_

ondepartment0_.dept_id=emps1_.dept_id_fk

复制代码

说明:



同时查询了Employee对象

list()方法返回的集合存放的实体对象的引用,每个Department关联的Employee集合都被初始化。

可以通过distinct关键字去重,也可以通过一个HashSet()去重(newArrayList<>(newLinkedHashSet(depts)))。

此种情况下,会忽略配置文件中检索策略。

(2)左外链接



复制代码

@Test

publicvoidtestHqlLeftJoin2(){

Listlist=session.createQuery("fromDepartmentdleftjoind.emps").list();

for(Object[]objects:list){

System.out.println(Arrays.asList(objects));

}

}

复制代码

复制代码

Hibernate:

select

department0_.dept_idasdept1_0_0_,

emps1_.emp_idasemp1_1_1_,

department0_.dept_nameasdept2_0_0_,

emps1_.emp_nameasemp2_1_1_,

emps1_.salaryassalary3_1_1_,

emps1_.dept_id_fkasdept4_1_1_

from

hibernate.departmentdepartment0_

leftouterjoin

hibernate.employeeemps1_

ondepartment0_.dept_id=emps1_.dept_id_fk

复制代码

说明:



list()方法返回的集合中存放的是对象数组类型。

根据配置文件来决定Employee集合的初始化时机。

7.迫切内连接和内连接



(1)迫切内连接(innerjoinfetch),与迫切左外链接类似,查询的时候同时将关联的另一端的对象进行了初始化。



(2)内连接(innerjoin),与左外链接类似,查询的时候是根据配置文件中的检索策略来决定另一端初始化的时机。



8.小结



(1)如果在HQL中没有显式的指定检索策略,则使用配置文件中的检索策略。



(2)HQL会忽略配置文件中设置的迫切左外链接检索策略,若想HQL采用迫切左外链接策略,就必须在HQL语句中显式的指定它。



二、QBC检索方式



1.设定各种查询条件



(1)like、gt、排序



复制代码

@Test

publicvoidtestQBC(){

Criteriacriteria=session.createCriteria(Employee.class);



criteria.add(Restrictions.like("empName","a",MatchMode.ANYWHERE));

criteria.add(Restrictions.gt("salary",1000F));

//排序

criteria.addOrder(Order.desc("salary"));



Listlist=criteria.list();

System.out.println(list);

}

复制代码

复制代码

Hibernate:

select

this_.emp_idasemp1_1_0_,

this_.emp_nameasemp2_1_0_,

this_.salaryassalary3_1_0_,

this_.dept_id_fkasdept4_1_0_

from

hibernate.employeethis_

where

this_.emp_namelike?

andthis_.salary>?

orderby

this_.salarydesc

复制代码

(2)and、or



复制代码

publicvoidtestQbc2(){

Criteriacriteria=session.createCriteria(Employee.class);



Conjunctionconjunction=Restrictions.conjunction();

conjunction.add(Restrictions.like("empName","a",MatchMode.ANYWHERE));

Departmentdepartment=newDepartment();

department.setDeptId(6);

conjunction.add(Restrictions.eq("dept",department));





Disjunctiondisjunction=Restrictions.disjunction();

disjunction.add(Restrictions.gt("salary",1000F));

disjunction.add(Restrictions.lt("salary",20000F));



criteria.add(conjunction).add(disjunction);



criteria.list();



}

复制代码

复制代码

Hibernate:

select

this_.emp_idasemp1_1_0_,

this_.emp_nameasemp2_1_0_,

this_.salaryassalary3_1_0_,

this_.dept_id_fkasdept4_1_0_

from

hibernate.employeethis_

where

(

this_.emp_namelike?

andthis_.dept_id_fk=?

)

and(

this_.salary>?

orthis_.salary
)

复制代码

2.分页查询



复制代码

@Test

publicvoidtestQbc4(){

Criteriacriteria=session.createCriteria(Employee.class);

//分页

intpageNo=2;

intpageSize=4;

Listlist=criteria.setFirstResult((pageNo-1)pageSize).setMaxResults(pageSize).list();

}

复制代码

复制代码

Hibernate:

select

this_.emp_idasemp1_1_0_,

this_.emp_nameasemp2_1_0_,

this_.salaryassalary3_1_0_,

this_.dept_id_fkasdept4_1_0_

from

hibernate.employeethis_limit?,

?

复制代码

3.聚集函数查询



复制代码

@Test

publicvoidtestQbc3(){

Criteriacriteria=session.createCriteria(Employee.class);

criteria.setProjewww.tt951.comction(Projections.max("salary"));



StringmaxSalary=criteria.uniqueResult().toString();

System.out.println(maxSalary);

}

复制代码

Hibernate:

select

max(this_.salary)asy0_

from

hibernate.employeethis

4.小结



(1)创建QBC查询:session.createCriteria()



(2)like关键字:Restrictions.like(),MatchMode.ANYWHERE



(3)排序:criteria.addOrder(),Order.desc、Order.asc



(4)AND:Conjunctionconjunction=Restrictions.conjunction()



(5)Or:Disjunctiondisjunction=Restrictions.disjunction()



(6)聚集函数:criteria.setProjection(Projections.max("salary"))



(7)查询单个对象:criteria.uniqueResult()



(8)查询对象列表:criteria.list()



三、本地SQL



复制代码

@Test

publicvoidtestNativeSql(){

Employeeemployee=newEmployee();

employee.setEmpId(5);

StringempName=(String)session.createSQLQuery("SELECTemp_nameFROMemployeewhereemp_id=?")

.setEntity(0,employee).uniqueResult();

System.out.printlnwww.baiyuewang.net(empName);

}

复制代码

复制代码

Hibernate:

SELECT

emp_name

FROM

employee

where

emp_id=?

bb2

复制代码

通过session.createSQLQuery()方法来创建本地SQL查询对象。



四、HQL的更新操作



@Test

publicvoidtestHqlUpdate(){

session.createQuery("deletefromEmployeewhereempId=?").setInteger(0,13).executeUpdate();

}

Hibernate:

delete

from

hibernate.employee

where

emp_id=?

五、总结



介绍了HQL、QBC、本地SQL查询。查询对象都是通过Session来创建的。依次为:session.createQuery()、session.createCriteria()、session.createSQLQuery()。



其中QBC提供了比HQL更为彻底的,更加面向Java编程风格的一种方式。在学习HQL的时候,需要重点关注迫切左外链接。本地化查询作为对HQL的一种补充。



学习的时候,注意对比学习。

献花(0)
+1
(本文系thedust79首藏)