HQL(Hibernate Query Language):具有与sql语言类似的语法规范,只不过sql是针对于数据表字段进行查询,而 HQL 是针对持久化对象,它用来取得对象。HQL 是完全面向对象的,具备继承,多态和关联等特性,除了JAVA类和属性 外HQL对大小写不敏感。HQL 查询依赖于 Query 类,每个 Query 实例对应一个查询对象。Query 接口用来执行 HQL,Query 接口实例可以从 Session 对象 session 中生成:
Query query = session.createQuery(“from User u where u.userName like ?”);
Query 的主要方法:
setXXX()方法:用于设置HQL中的问号或变量的值,每一个方法都有两种重载形式,以 setString()为例:
setString(int position,String value):用于设置HQL中的 ”?” 的值;期中position代表 ”?” 在HQL中的位置,value为 ”?” 设置的值.例如:
Query query = session.createQuery(“from User u where u.age > ? and u.userName like ?”);
query.setInteger(0,12);
query.setString(1,”%Tom%”);
list()方法:返回查询结果,并把查询结果转变为 List对象
excuteUpdate()方法:执行更新或删除语句
在查询时,如果希望查询得到的是具体的关联的对象。则应该在查询语句中加上 fetch 关键字。例如:
from Customers as customer inner join fetch customer.orders as order
查询 Customers 对象的时候,默认只有 Customers 的内容,并不包含 orders 集合的信息,在 Customers.hbm.xml 里设置lazy=“false”可以同时取出关联的所有 orders 内容.但若既想要 hibernate 默认的性能又想要临时的灵活性,则可以使用 fetch。总之,fetch就是在代码这一层给你一个主动抓取得机会fetch 关键字只对 inner join 和 left join 有效。对于 right join 而言, 由于作为关联对象的 Customers 对象可能为 null,所以无法通过 fetch 关键字强制 Hibernate 进行集合填充操作。这意味着只能对返回集合中的各个数组进行处理。
在通过JDBC操作数据时,只能通过SQL语句来加载所需要的数据由于O-R Mapping的帮助,Hibernate总共有4种数据加载方式:即时加载、延迟加载、预先加载、批量加载。
1.即时加载:当实体加载完成后,立即加载该实体所关联的数据。例如:客户和订单之间的一对多关联映射:当查询 Customers 实体时,会自动加载它所关联的 Orders 实体对象,因此会出现二条查询语句。即时加载的基本原理,当宿主实体加载时,会立即自动加载关联的实体对象,并完成关联实体对象的属性填充和实体对象的构造。即时加载中,当加载 Customers 对象时,通过另一条查询语句自动加载了它所关联的实体对象,但是如果只需要 Customers 对象数据,而不需要它所关联的 Orders 对象数据,就造成了性能的损耗。
2.延迟加载机制就是为了解决这个问题。当查询 Customers 对象时,并没有立即加载它所关联的Orders 对象,只有执行确实获取关联的 Orders 对象数据时,才会发起对关联对象的查询。延迟加载机制,只有当确实需要获取关联数据时,才去真正加载关联对象
3.预先加载:与即时加载类似,预先加载时,实体及其关联的对象同时读取,不同的是预先加载只通过一条 SQL 语句(基于外连接[outer join])完成同时读取.预先加载通过 outer-join 完成关联数据的加载。对于集合属性不推荐使用。
4.批量加载,通过批量提交多个限定条件,一次完成多个数据的 读取:
select * from customer where id=’1’;
select * from customer where id=’2’;
将以上两个SQL语句合并:
select * from customer where id=’1’ or id=’2’;
当使用批量加载时,Hibernate会自动在当前session中查找是否还有同类型的待加载的实体对象,如果有就将查询条件合并到当前的查询语句中,这样就通过一次数据库操作完成了多次读取任务,从而提高读取性能。
如需启用批量加载,须配置实体类的class元素:
<class name=”customer” table=”customer” batch-size=”5” >
batch-size属性:指定批量加载尺寸以及启用批量加载,以上配置每次最多同时加载5个同类型实体对象。
在利用Hibernate开发DAO模块时,和Session打交道最多,所以如何合理的管理Session,避免Session的频繁创建和销毁,对于提高系统的性能来说是非常重要的。Session是由SessionFactory负责创建的,而SessionFactory的实现是线程安全的,多个并发的线程可以同时访问一个SessionFactory并从中获取Session实例,但 Session 却是线程不安全的。多个线程同时使用一个Session实例进行CRUD,就有可能导致数据存取的混乱。建议为每个请求对应一个 Session。为了达到这种效果,推荐使用一个 ThreadLocal 变量,把 Session 绑定到处理客户端请求的线程上去。这种方式可以让运行在该线程上的所有代码轻松的访问 Session。
ThreadLocal是一个线程隔离(或者说是线程安全)的变量存储的管理实体(注意:不是存储用的),以Java类方式表现当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。一个ThreadLocal变量类似一个HashMap,它的key集合就是Thread.currentThread(),它的value集合就是要跨域共享的对象。当代码从threadLocal变量get()来取对象的时候,就是以代码运行所在的currentThread为key,去找它对应的value共享对象。因而在一个thread里面,任何被该thread调用到的类,方法代码都可以取到同一个跨域共享对象。而不同的thread则取到不同的对象。