Hibernate 提供了以下几种检索对象的方式:
1.导航对象图检索方式:根据已加载的对象导航到其他对象
2.OID检索方式:按照对象的OID来检索对象
3.HQL检索方式:使用面向对象的HQL查询语言
4.QBC检索方式:使用QBC API 来检索对象,这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口
5.本地SQL检索方式:使用本地数据库的SQL查询语句
步骤:
通过session的createQuery()创建一个Query对象
动态绑定参数
调用Query 相关方法执行
1.基于位置的参数:
String hql="from Employee e where e.salary > ?0 and e.email like ?1";
Query query= session.createQuery(hql);
query.setFloat(0,0).setString("ema","%9%");
List employeeList=query.list();
2.基于命名参数的:
String hql="from Employee e where e.salary > :sal and e.email like :ema and e.department=:dep order by e.id";
Query query= session.createQuery(hql);
query.setFloat("sal",0).setString("ema","%9%").setEntity("dep",department);
3.分页查询:
setFirstResult() :设置起始查询页(默认从0)
setMaxResult() :设置每次查询最多页数
String hql="from Employee";
Query query=session.createQuery(hql);
int pageNo=3;
int pageSize=2;
List list=query.setFirstResult(0).setMaxResults(pageSize).list();
4.在映射文件中定义命名查询语句
在Hibernate的映射文件中定义字符串的形式的查询
使用query元素用于定义一个HQL查询语句,它和class元素并列
:minSal and e.salary < :maxSal]]>
因为使用了大于小于号,所以使用包裹起来
使用时如下引用:
Query query=session.getNamedQuery("salaryEmps");
List list=query.setFloat("minSal",0).setFloat("maxSal",2).list();
5.投影查询
查询结果仅包含实体的部分属性,通过select关键字实现
query的list()方法返回集合中包含数组类型的元素,每个对象数组代表查询结果中的一条记录
可以在持久化类中定义一个对象的构造器来包装投影查询返回的记录,使之面向对象
String hql="select new Employee (e.id,e.name) from Employee e where e.department= :dep ";
Query query=session.createQuery(hql);
Department department=new Department();
department.setId(1);
List list=query.setEntity("dep",department).list();
for(Employee employee:list){
System.out.println(employee.getId()+":"+employee.getName() );
}
6.报表查询:
->报表查询用于对数据分组和统计,与SQL一样,HQL利用GROUP BY 关键字对数据分组,用HAVING关键字对分组数据设定约束条件
-> 在HQL查询语句中可以调用聚合函数:count(),min(),max().sum().avg();
String hql="select max(e.id),min(e.id) from Employee e " +
"where e.id > 0";
Query query=session.createQuery(hql);
List
7.左外连接:
左外链接,会将左表所有信息加上符合条件的右表信息返回:
1.迫切左外连接: left join fetch:
list()方法返回的集合存放实体对象的引用,每个Department对象关联的Employee集合都被初始化,存放所有关联的Employee的实体对象,查询结果可能包含实体对象
String hql="from Department d" +
" left join fetch d.employeeSet";
Query query=session.createQuery(hql);
List list= query.list();
2.左外连接:left join :
list()返回的集合中存放的时对象数组类型
根据配置文件来决定Employee集合的检索策略(lazy等)
3.如何去除重复的元素:
①使用 distinct :如下可以根据Deparment是否重复来去重
String hql="select distinct d from Department d left join fetch d.employeeSet";
②使用LinkHashSet<>:保证其中的元素不重复而且有序
List list= query.list();
list=new ArrayList<>(new LinkedHashSet<>(list));
8.内连接
内连接会返回符合条件的左表内容
1.迫切内连接:
和迫切左连接类似,返回的后直接初始化所有的集合
如下可以看到在getName之前就已经把所有的department集合初始化了
String hql="select e from Employee e inner join fetch e.department";
Query query=session.createQuery(hql);
List list=query.list();
for(Employee employee:list){
System.out.println(employee+employee.getDepartment().getName());
}
2.内连接
返回不会初始化集合,要在调用的时候才会发送select语句
String hql="select e from Employee e inner join e.department";
Query query=session.createQuery(hql);
List list=query.list();
for(Employee employee:list){
System.out.println(employee+employee.getDepartment().getName());
}
注意点:
->使用内连接时,如果查询的是一个department,则不会反复查询多次
->左外内连接必须在HQL语句中显式的调用,不能在映射文件中配置
->映射文件配置为辅,HQL语句会覆盖其.
HQL的update,delete:
String hql="update Department d set d.name=:rename where d.name= :name ";
Query query=session.createQuery(hql).setString("name","a0").setString("rename","pp");
query.executeUpdate();
String hql="delete from Department d where d.name='pp' ";
Query query=session.createQuery(hql);
query.executeUpdate();
QBC查询就是通过使用Hibernate 提供的Query By Criteria API来查询对象,这种API封装了SQL语句的动态拼装,对查询提供了更加面向对象的功能接口
创建Criteria对象,调用list()查询
Criteria criteria=session.createCriteria(Employee.class);
criteria.list();
创建复杂的查询:
Criteria criteria=session.createCriteria(Employee.class);
//criterion 是个接口
//conjunction and
//disjunction or
Conjunction conjunction=Restrictions.conjunction();
conjunction.add(Restrictions.ge("salary",1F));
conjunction.add(Restrictions.ge("salary",2F));
criteria.add(conjunction);
Disjunction disjunction=Restrictions.disjunction();
disjunction.add(Restrictions.ge("salary",1F));
criteria.add(disjunction);
criteria.list();
使用HQL是无法使用insert语句的,只能使用本地的SQL语句代替:
String sql="insert into tb_department value (?0,?1)";
Query query=session.createSQLQuery(sql).setString(1,"ii").setInteger(0,13);
query.executeUpdate();