HIbernate提供了如下几种检索对象的方式:java
①、导航对象图检索方式:根据已经加载的对象,导航到其余对象。例如,对于已经加载的Customer对象,调用它的getOrders().iterator()方法就能够导航到所关联的Order对象。数据库
②、OID检索方式:按照对象的OID来检索对象,session的get()和load()方法提供了这种功能。若是在应用程序中事先知道了OID,就可使用这种检索对象的方式。编程
③、HQL检索方式:使用面向对象HQL查询语言,Hibernate提供的Query接口,它是Hibernate提供的专门的HQL查询接口,可以执行各类复杂的HQL查询语句。缓存
④、QBC检索方式:使用QBC(Query By Criteria)API来检索对象,安全
⑤、本地SQL检索方式。性能优化
⑥、QBE检索方式:QBC的子功能。session
1、Hibernate检索方式简介:app
当直接使用JDBC API查询数据库时,必须在应用程序中嵌入冗长的SQL语句。性能
一、HQL检索方式(Hibernate Query Language) HQL是面向对象查询语言。fetch
二、QBC检索方式(Query By Criteria) QBC API提供了检索对象的另外一种方式,它主要是有Criteria接口、Criterion接口和Expression类组成,它支持在运行时动态生成查询语句。
三、QBE检索方式(Query By Example) 它是QBC的子功能。QBE容许先建立一个对象样板,而后检索出全部和这个样板相同的对象。
四、Sql检索方式:Sql检索方与HQL检索方式都使用Query接口,区别在于SQL检索方式经过Session的createSQLQuery()方法来建立Query对象。
2、HQL检索方式
一、使用别名:
经过HQL检索一个类的实例时,若是查询语句的其余地方须要引用它,应该为这个类指定一个别名,例如:from Customer as customer where customer.name=:name。as关键字用于设定别名,也能够将as关键字省略。
二、多条查询:
HQL和QBC都支持多态查询,多态查询指查询出当前类及全部子类的实例。
三、对查询结果排序
HQL与QBC都支持对查询结果排序,HQL采用order by关键字对查询结果排序,而QBC采用Order类对查询结果排序。
//hql检索方式
Query query=session.createQuery("from Customer customer order by customer.name");
//QBC方式
Criteria criteria=session.createCriteria(Customer.class);
criteria.addOrder(Order.asc("name"));
四、分页查询:
Query和Criteria接口都提供了用于分页显示查询结果的方法:
setFirstResult(int firstResult):设定从哪个对象开始检索。
setMaxResult(int maxResult):设定一次最多检索出的对象数目。
五、检索单个对象
Query和Criteria接口都提供了如下用以执行查询语句并返回查询结果的方法
list()方法:返回一个list类型的查询结果,在List集合中存放了全部知足查询条件的持久化对象。
uniqueResult()方法:返回单个对象
六、在HQL查询语句中绑定参数
session=HibernateUtil.getSession(); Query query=session.createQuery("from Customer as customer where customer.name='"+name+"'"); List customers=query.list(); return customers;
上面的代码尽管能够,可是不安全,Hibernate采用参数绑定机制来避免以上问题,Hibernate的参数绑定机制依赖于JDBC API中PreparedStatement的预约义Sql语句功能。参数绑定有如下优势:
①、很是安全。
②、可以利用底层数据库预编译SQL语句的功能,提供查询数据的性能。预编译是指在底层数据库系统只须要编译SQL语句一次,把编译出来的可执行代码保存在缓存中,若是屡次执行相同形式的SQL语句,不须要从新编译,只要从缓存中得到可执行代码便可。
参数绑定的形式有两种:
<1>、按参数名字绑定
在HQL查询语句中定义命名参数,命名参数以“:”开头,形式以下:
Query query=session.createQuery("from Customer customer where customer.name=:name and customer.age=:age");
以上的HQL语句中定义了两个参数:name,age。下面接下里调用Query的setXXX()方法绑定参数。
query.setString("name",name);
<2>、按参数位置绑定
在HQL中使用“?”来定义参数的位置,则HQL为
Query query=session.createQuery("from Customer customer where customer.name=? and customer.age=?");
query.setString(0,name);
query.setInteger(1,age);
七、在映射文件中定义命名查询语句
Hibernate容许再映射文件中定义字符串形式的查询语句。在程序中经过Session的getNamedQuery()方法获取该查询语句。
八、设定查询条件
HQL查询语句也经过where字句来设定查询条件,值得注意是,在where字句中给出的是对象的属性名,而不是字段名。对于QBC查询,必须建立一个Criterion对象来设定查询条件。
HQL和QBC支持的各类运算
HQl运算符 | QBC运算符 | 含义 |
= | Expression.eq() | 等于 |
<> | Expression.not(Expression.eq()) | 不等于 |
> | Expression.gt() | 大于 |
>= | Expression.ge() | 大于等于 |
< | Expression.lt() | 小于 |
<= | Expression.le() | 小于等于 |
is null | Expression.isNull() | 等于空值 |
is not null | Expression.isNotNull() | 非空值 |
in | Expression.in() | 等于列表中的某一值 |
not in | Expression.not(Expression.in()) | |
between 值1 and 值2 | Expression.between() | |
not between 值1 and 值2 | Expression.not(Expression.between()) | |
like | Expression.like() | |
and | Expression.and()或者Expression.conjunction() | |
or | Expressioin.or() |
|
not | Expression.not() |
九、链接查询
HQL与QBC也支持各类各样的连接查询,如内链接、外链接和交叉链接,迫切内链接、迫切外链接。
查询类型 | HQL语法 | QBC语法 |
内链接 | inner join或 join | Criteria.createAlias() |
迫切内链接 | inner join fetch 或join fetch | 不支持 |
隐式内链接 | 不支持 | |
左外链接 | left outer join或者left join | 不支持 |
迫切左外链接 | left outer join fetch 或者 left join fetch | FetchMode.EAGER |
右外链接 | right outer join | 不支持 |
交叉链接 | ClassA,ClassB | 不支持 |
3、高级查询-------动态查询
一、HQL与QBC可以完成许多相同的任务,相比之下,HQL能更加直观的表达复杂的查询语句,而经过QBC表达复杂的查询语句很麻烦。所以若是,在程序运行前就明确了查询语句的内容(也成为静态查询),应该优先考虑HQL查询方式。可是若是只有在程序运行时才能明确查询 语句的内容(也称为动态查询),QBC比HQL更加方便。
在实际应用中,常常有这样的查询需求:用户在客户界面的查询窗口输入查询条件,按下查询按钮后,业务层执行查询操做,返回匹配的查询结果。
经过HQL来生成动态查询语句:
public List findCustomers(String username,String password){ session=HibernateUtil.getSession(); StringBuffer hqlStr=new StringBuffer("from SysUser as user"); if(username!=null) hqlStr.append(" where user.username like :username"); if(password!=null && username!=null) hqlStr.append(" and user.password=:password"); if(password!=null && username==null) hqlStr.append(" where customer.password=:password"); Query query=session.createQuery(hqlStr.toString()); if(username!=null) query.setString("username", username); if(password!=null) query.setString("password", password); List list=query.list(); System.out.println(list.size()); return list; }
若是采用QBC检索方式,能够简化编程:
public List findCustomers2(String username,String password){ session=HibernateUtil.getSession(); Criteria cri=session.createCriteria(SysUser.class); if(username!=null) cri.add(Expression.like("username", username,MatchMode.ANYWHERE)); if(password !=null) cri.add(Expression.eq("password", password)); List list=cri.list(); System.out.println(list.size()); return list; }
也可使用QBE检索方式:
public List findCustomers3(Customer customer){ session=HibernateUtil.getSession(); Example exampleCustomer=Example.create(customer); exampleCustomer.ignoreCase().enableLike(MatchMode.ANYWHERE); exampleCustomer.excludeZeroes(); Criteria cri=session.createCriteria(SysUser.class).add(exampleCustomer); return cri.list(); }
二、集合过滤
Session的createFilter()方法用来过滤集合。
4、本地SQL查询
HIbernate对本地SQL查询提供了内置的支持,为了把SQL查询返回的关系数据映射为对象,须要在SQL查询语句中为字段指定别名,Session的createSQLQuery()方法。
5、查询性能优化
Hibernate主要从如下几个方面来优化查询性能:
一、下降访问数据库的频率,减小select语句的数目。实现手段:
①、使用迫切左外链接或迫切内链接检索策略。
②、对延迟检索或当即检索设置批量检索数目。
③、使用查询缓存。
二、避免多余加载程序不须要访问的数据,实现手段:
①、使用延迟检索策略。
②、使用集合过滤。
三、避免报表查询数据占用缓存。实现手段为利用投影查询,查询出实体的部分属性。
四、减小select语句中的字段,从而下降访问数据库的数据量。实现手段:利用Query的iterate()方法。
6、iterate()方法
Query接口的iterate()方法和list()方法都能执行SQL查询语句,可是前者在有些状况下能轻微 提升查询性能。例如,如下程序代码两次检索Customer对象。
Query query1=session.CreateQuery("from Customer c");
List result1=query1.list();
Query query2=session.CreateQuery("from Customer c where c.age<30");
List result2=query2.list();
当第二次从数据库检索Customer对象时,Hibernate执行的SQL查询语句为select id,name ,age from customers where age <30
因为和以上查询结果对应的Customer对象已经存在于Session的缓存中,所以在这种状况下,Hibernate不须要从新建立Customer对象,只须要根据查询结果中的ID字段值返回缓存中匹配的Customer对象。可见,当第二次从数据库中检索Customer对象时,在select语句中其实只须要包含customer表的ID字段就能够了。
Query接口的iterate()方法首先检索ID字段,而后根据ID字段到Hibernate的第一级缓存以及第二级缓存中查找匹配的Customer对象,若是存在,就直接把它加入到查询结果集中,不然就执行额外的select语句,根据ID字段到数据库中检索该对象。
7、查询缓存
对于常用的查询语句,若是启用了查询缓存,当第一次执行查询语句时,Hibernate会把查询结果存放在第二级缓存中。之后再次执行该查询语句时,只需从缓存中得到查询结果,从而提供查询性能。若是查询结果中包含实体,第二级缓存只会存放实体的OID,而对于投影查询,第二级缓存会存放全部的数据值。
后面咱们会详细介绍缓存。