7.Hibernate 檢索
1.Hibernate檢索方式
檢索方式簡介:
導航對象圖檢索方式:
根據已經加載的對象,導航到其他對象。
OID檢索方式:
按照對象的OID來檢索對象。Session 的 get() 和 load() 方法提供了這種功能。
HQL檢索方式:
使用面向對象的HQL查詢語言。
QBC檢索方式:
使用QBC(Query By Criteria)API來檢索對象。這種API封裝了基於字符串形式的查詢語句,提供了更加面向對象的接口。
本地SQL檢索方式:
使用本地數據庫的SQL查詢語句。
HQL簡介:
HQL是一種面向對象的查詢語言,和SQL查詢語言有些類似。
在Hibernate提供的各種檢索方式中,HQL是使用最廣的一種檢索方式。
Query接口是HQL查詢接口,提供各種查詢功能。
HQL實體檢索:
where 子句。
where 子句中給出的是類的屬性名而不是數據庫表字段名,其中屬性名必須區分大小寫。
String hql = "from User where userName=‘張三‘"; Query query = session.createQuery(hql); List userList = query.list();
HQL支持的各種運算符:
程序中指定的連接類型 |
HQL運算符 |
比較運算符 |
=、<>、>=、<=、>、<、is null、is not null |
範圍運算符 |
in、not in、between…and、not between…and |
字符串模式匹配運算符 |
like |
邏輯運算符 |
and、or、not |
HQL使用別名查詢:
HQL檢索一個類的實例時,如果查詢語句的其它地方需要引用它,可以給類指定一個別名。
as 關鍵字用來指定別名,as 關鍵字也可以省略。
from User where userName=‘張三‘ from User as u where u.userName=‘張三‘ from User u where u.userName=‘張三‘
HQL支持多態查詢:
多態查詢指查詢出當前類以及所有子類的實例。
Employee 有兩個子類:HourlyEmployee 和 SalariedEmployee。
Query query = session.createQuery("from Employee"); List employeeList = query.list();
HQL檢索單個對象:
HQL查詢返回結果方法:
list():返回List類型的查詢結果,返回所有滿足條件的對象。
uniqueResult():返回單個對象。
Query query = session.createQuery("from User u where u.userName=‘張三‘"); User user = (User)query.uniqueResult();
HQL分組與排序:
order by 字句:
from User u order by u.userName
from User u order by u.userName desc
from User u order by u.userName, u.id desc
group by 子句:
select count(u) from User u group by u.age
having子句:
select count(u) from User u group
by u.age having count(u)<4
HQL參數綁定:
前述HQL中查詢參數均直接在HQL中表達。
String hql = "from User as u where u.userName=‘張三‘"; String hql = "from User as u where u.userName =" + name;
缺陷:
代碼更加零亂,可讀性降低;
難以進行性能優化;
引入額外的安全風險。
在HQL查詢語句中按照參數位置綁定參數。
setParameter() 參數位置從0開始。
String hql = "from User u where u.userName=?"; Query query = session.createQuery(hql); query.setParameter(0, "張三"); List<User> userList = query.list();
在HQL查詢語句中按參數名稱綁定參數。
String hql = "from User u where u.userName=:name"; Query query = session.createQuery(hql); query.setParameter("name", "張三"); List<User> userList = query.list();
HQL的綁定參數方法:
setParameter() 綁定任意類型的參數。
setProperties() 用於把命名參數與一個對象的屬性值綁定,並且參數名稱要與對象屬性名稱一致。
HQL實體更新:
不使用HQL的實體更新;
Transaction tx = session.beginTransaction(); User user = (User) session.get(User.class, 1); user.setUserName("Tom"); tx.commit();
HQL實現實體更新的方式。
Transaction tx = session.beginTransaction(); String hql = "update User set userName=‘Tom‘ where id=2"; Query query = session.createQuery(hql); int ret = query.executeUpdate(); tx.commit();
HQL實體刪除:
Transaction tx = session.beginTransaction(); String hql = "delete from User where id = 1"; Query query = session.createQuery(hql); int ret = query.executeUpdate(); tx .commit();
HQL子查詢:
HQL支持在 where 子句中嵌入子查詢語句,並且子查詢語句必須放在括號內。
查詢訂單數量大於0的所有用戶:
from User u
where 0<(select count(o) from u.orderSet o)
對應的SQL語句:
select * from user u where 0<(select count(o) from orders o where u.id=o.userId )
HQL子查詢說明以下幾點:
子查詢分為相關子查詢和無關子查詢;
相關子查詢:子查詢語句引用了外層查詢語句定義的別名。
無關子查詢:子查詢語句沒有引用外層查詢語句定義的別名。
HQL子查詢功能依賴於底層數據庫對子查詢的支持;
HQL子查詢返回的是多條記錄,使用以下關鍵字量化。
all、any、some、in、exists。
如果HQL子查詢的是集合,HQL提供了一組操作集合的函數。
size(),獲得集合中元素的個數;
maxIndex(),對於建立索引的集合,獲得最大索引值;
minIndex(),對於建立索引的集合,獲得最小索引值;
elements(),獲得集合中所有元素。
HQL分頁查詢:
做批量查詢時,如果數據量很大就需要分頁功能,HQL提供了用於分頁查詢的方法:
setFirstResult(int firstResult)—設定從哪個對象開始檢索。
setMaxResult(int maxResult)—設定一次檢索對象的數目。
HQL引用查詢 :
引用查詢指在映射文件中定義查詢語句。
在O/R映射xml文件中,用與<calss>元素同級的<query name="XXX">元素定義一個HQL查詢語句。
<query name="findUser">from User</query>
程序中通過session.getNamedQuery("XXX")調用對應的HQL。
Query query = session.createNamedQuery("findUser", User.class); List userList = query.list();
Qauery By Criteria(QBC) 可以看作是傳統SQL的對象化表示。
它主要由Criteria接口,Criterion接口,Expression類組成。
QBC表達式:
檢索姓名為 Erica 的所有用戶。
Criteria criteria=session.createCriteria(User.class); Criterion c1= Restrictions.eq("userName", "張三"); criteria.add(c1); List result = criteria.list();
步驟:
調用 Session 的 createCriteria() 創建 Criteria 實例;
通過 Restrictions 設定查詢條件;
調用 Criteria 實例的 list() 方法執行查詢。
運算類型 |
方法 |
描述 |
比較運算符
|
Restrictions.eq |
等於 |
Restrictions.ne |
不等於 |
|
Restrictions.gt |
大於 |
|
Restrictions.ge |
大於等於 |
|
Restrictions.lt |
小於 |
|
Restrictions.le |
小於等於 |
|
Restrictions.isNull |
等於空值 |
|
Restrictions.isNotNull |
非空值 |
運算類型 |
方法 |
描述 |
範圍運算符 |
Restrictions.in |
等於列表中的某個值 |
Restrictions.not(Restrictions.in) |
不等於列表中的任意值 |
|
Restrictions.between |
大於等於值1小於等於值2 |
|
字符串模糊匹配 |
Restrictions.like |
字符串模糊匹配 like |
邏輯運算符 |
Restrictions.and |
邏輯與 |
Restrictions.or |
邏輯或 |
|
Restrictions.not |
邏輯非 |
本地SQL查詢:
HQL 和 QBC 查詢,Hibernate 會生成標準的 SQL 語句適合不同的數據庫平臺。
有時需要根據底層數據庫生成特殊的 SQL 查詢語句, Hibernate 對本地 SQL 查詢提供了內置支持。
查詢所有的用戶信息:
String sql = "select * from user"; NativeQuery query = session.createNativeQuery(sql, User.class); List list = query.list();
步驟:
調用session.createNativeQuery()創建NativeQuery實例,並指定查詢的實體類型;
調用NativeQuery實例的list() 方法執行查詢(如果查詢單個對象,調用uniqueResult() )。
2.Hibernate檢索策略
檢索策略:
立即檢索:立即加載檢索方法指定的對象。
加載多於需要的對象白白浪費內存空間;
select 語句數量多,頻繁訪問數據庫,影響系統性能。
延遲檢索:延遲加載檢索方法指定的對象。
避免多加載應用程序不需要訪問的數據對象。
迫切左外連接檢索:利用SQL外連接查詢功能加載檢索方法指定對象。
減少執行select語句的數量,減少數據庫訪問,提高系統性能。
檢索執行分析:
Query query = session.createQuery("from User");
List userList = query.list();
Hibernate在執行檢索方法時,要獲取以下兩種信息:
類級別的檢索策略:Hibernate檢索方法指定的檢索對象(User)的檢索策略;
關聯級別的檢索策略:與檢索方法指定的檢索對象相關聯的對象(Order)的檢索策略。
類級別和關聯級別可選的檢索策略:
檢索策略的作用域 |
可選的檢索策略 |
默認的檢索策略 |
影響到的檢索方法 |
類級別 |
立即檢索 |
立即檢索 (除Session的load()默認延遲檢索) |
影響Session的load()方法 |
延遲檢索 |
|||
關聯級別 |
立即檢索 |
默認延遲檢索 |
影響所有檢索方法 |
延遲檢索 |
|||
迫切左外連接檢索 |
|||
影響session的load()和get()方法
|
三種檢索策略的運行機制:
檢索策略類型 |
類級別 |
關聯級別 |
立即檢索 |
立即加載 檢索方法指定的對象 |
立即加載與檢索方法指定的對象相關聯的對象 |
延遲檢索 |
延遲加載 檢索方法指定的對象 |
延遲加載與檢索方法指定的對象相關聯的對象 |
迫切左外連接 <class name="User" table="USER" lazy="false">
檢索 |
不適 User user = session.load(User.class, new Integer(1));
用 |
通過左外連接加載與檢索方法指定的對象相關聯的對象 |
類級別檢索策略:
立即檢索(加載):映射配置文件中<class>元素的 lazy 屬性設置為 false。
<class name="User" table="USER" lazy="false">
延遲檢索(加載):映射配置文件中<class>元素的 lazy 屬性設置為 true。
<class name="User" table="USER" lazy="true">
立即檢索:
立即檢索
Hibernate立即執行 "select* from user where id=1" 。
延遲檢索:
User user = session.get(User.class, new Integer(1));
延遲檢索
創建 User 的代理類實例(代理類是 Hibernate 動態生成的User的擴展類);
Hibernate 創建的 User 代理類的實例僅僅初始化了 OID 屬性,其他屬性均為 null;
當程序第一次訪問代理類實例時(比如user.getX()),Hibernate會初始化代理類實例,執行 select 語句;
如果程序訪問 User 的 getId() 方法時,Hibernate並不會初始化代理類實例,因為 id 值已經存在。
類級別的檢索策略只會影響到 Session 的 load() 方法,對 get() 和其它查詢不起作用。
延遲加載對 load() 方法的影響:
如果數據庫中不存在對應的對象不會拋出異常,只有在調用 user.getXX() 時才會拋異常;
代理類實例只能在當前 Session 範圍內初始化;
Hibernate.initialize() 方法可以顯示初始化代理類實例。
關聯級別檢索策略:
Hibernate需要確定以下檢索策略:
User 類級別的檢索策略;
User 一對多關聯的Order對象的檢索策略,User.hbm.xml 中<set>元素 lazy 和 outer-join 屬性。
在映射文件中用 <set>元素 來配置 一對多 和 多對多 關聯關系。
lazy |
outer-join |
檢索策略 |
flase |
false |
立即檢索策略。 |
false |
true |
迫切左外連接檢索,在配置文件中如果有多個<set>元素,只允許一個設置 outer-join=true。 |
true |
false Order order = session.get(Order.class, new Integer(1));
|
延遲加載,優先考慮的檢索策略。 |
true |
true |
迫切左外連接檢索。 |
關聯級別檢索策略-多對一
Hibernate需要確定以下檢索策略:
Order 類級別的檢索策略;
Order 多對一關聯的 User 對象檢索策略,Order.hbm.xml 中 <many-to-one>元素 outer-join 屬性和 User.hbm.xml 中<class>元素的 lazy 屬性。
Order order = session.get(Order.class, new Integer(1));
關聯級別檢索策略 - 多對一 和 一對一
在映射文件中用 <many-to-one>元素 和 <one-to-one>元素 來分別設置多對一和一對一關聯關系。
<many-to-one>元素的 outer-join 屬性:
auto、true、false三種取值。
關聯級別檢索策略 - 多對一
<many-to-one>元素的outer-join屬性值 |
對應one方<class>元素的lazy屬性值 |
檢索many方(Orders)對象時,對關聯的one方(Users)對象的檢索策略 |
auto |
false |
迫切左外連接檢索 |
auto |
true |
延遲檢索 |
true |
true or false |
迫切左外連接檢索 |
false |
false |
立即檢索 |
false |
true |
延遲檢索 |
使用註解配置檢索策略
fetch 參數可以設置為 FetchType.LAZY 或者 FetchType.EAGER。
EAGER:通過 outer join select 直接獲取關聯的對象。
LAZY(默認值):在第一次訪問關聯對象的時候才會觸發相應的 select 操作。
7.Hibernate 檢索