1. 程式人生 > >7.Hibernate 檢索

7.Hibernate 檢索

add 配置文件 sts lsp hql查詢 delet als 集合 hour

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 檢索