天天看點

hibernate學習筆記(三)

hibernate的一些雜記:

1.sessionfactory的用法:

sessionfactory是線程安全的,構造 sessionfactory 很消耗資源

sessionfactory = new configuration().configure().addclass(**).addclass(**).buildsessionfactory();

session session = sessionfactory.opensession();

在這裡addclass的好處是不需要在hibernate.cfg.xml中聲明domain中各個實體對應的配置檔案

2.二級緩存

二級緩存中的類緩存,隻适用于id查詢的方式(get()或load()),對于hql的方式不可以,這個時候可以配置查詢緩存,使用查詢緩存需要先在hibernate.cfg.xml中開啟查詢緩存,然後在查詢到時候setcacheable(true).

時間戳緩存:指定hibernate的二級緩存會自動檢測,如果使用了update或delete語句,則會把資料清出緩存,重新查詢。注::但是這是一級緩存session中的内容不會被重新整理,是以要手動refresh().

list()方法預設不會使用緩存,除非調用了setcacheable(true),但是如果hql一變或者參數一遍,緩存就失效了,但是用iterate()查詢,就可以。

3.iterate()查詢的原理:

先執行一個查詢,查詢所有的符合條件的id,再使用每一個對象時,會根據id去緩存中查,如果查得到直接使用,如果查不到,那麼就查出緩存中沒有的相應資料。

4.關于級聯

在設定了關聯關系以後,如果主從對象存在級聯關系,可以用cascade屬性來設定,在使用時應仔細分析對象的級聯關系,是否需要級聯删除等操作。

5.在使用的時候

從對象的角度來說:讓雙方都設定關聯關系比較好。是以用inverse屬性配置是否由對方維護關聯關系。一般都是讓一的一方去放棄維護關聯關系。為了使查詢的集合元素有順序,可以配置order-by屬性

從資料庫的角度來說,隻要讓一方設定關聯就可以。是以在用時候可以讓一的一方維護多的一方,也可以讓多的一方維護一的一方。這樣都會比雙方同時維護性能要好。但是這樣做的效果缺點是:代碼不清晰。

注::在一對多中,維護關聯關系就是指更新外鍵的值

在save的時候應該先儲存無外鍵的一方,再儲存有外鍵的一方(基于外鍵的一對一也同樣),這樣會節省一個update語句

6.主鍵生成政策:native---資料庫的自動增長(oracle不支援)(identity,sequence[oracle],hilo)increment存在多線程問題。聯合主鍵

7.dml語句不經過緩存,要手動session.refresh();

8.  query和criteria接口

都是查詢接口,query執行個體包裝了hql查詢語句,hql是面向對象的,他引用類名及類的屬性名,而不是表名和字段名。criteria接口完全封裝了基于字元串形式的查詢語句,比query接口更面向對象,他擅長執行動态查詢

9.  hibernate通路持久化類屬性的政策

propertye(預設值):

表明hibernate通過getxxx和setxxx來通路類屬性。推薦使用。提高域模型透明性。

field

hibernate通過java反射機制直接通路類屬性。對于沒有get與set方法的屬性可設定該通路政策。

noop

它映射java持久化類中不存在的屬性,即主要用于hql(用query接口測試,使用hql語句)中,當資料庫中有某列,而實體中不存在的情況。

<!-- 該屬性在customer類中有get與set方法 -->

<property name="name" column="name"type="string"/> 

<!-- 該屬性在customer類中不存在get和set方法 -->

<property name="name" column="name"type="string" access="field" />

<!-- 該屬性在customer類中不存在,但在資料庫存在該字段。

使用noop處理,查詢的時候忽略該字段-->

<property name="name"column="name" type="string" access="noop"/>

10.利用<property>元素的formula屬性,用來設定一個sql表達式,hibernate将根據它來計算出派生屬性的值。

如果指定了formula 屬性,則就會insert=”false” update=”false”

11.java與hibernate如何區分對象

java語言按記憶體位址(==)或equals()方法區分不同的對象

hibernate中用對象表示符(oid)來區分對象

oid是關系資料庫中的主鍵在java對象模型中的等價物。在運作時,hibernate根據oid來維持java對象和資料庫記錄的對應關系。

hibernate使用oid來區分對象,不是equals()方法!是以不重寫持久化類的hashcode()與equals()方法hibernate也可以正确運作(但要放到hashset等集合中時要注意需要重寫這兩個方法)。

12.  list是有序集合,是以持久化到資料庫時必須增加一列來表示集合元素的次序。

集合屬性隻能以接口聲明(當持久化某個執行個體時, hibernate 會自動把程式中的集合實作類替換成 hibernate 自己的集合實作類)

list元素要求用list-index的子元素來映射有序集合的次序列。

集合的屬性的值會存放有另外的表中,須以外鍵關聯,用 key 元素來映射外鍵列

13.在映射一對多的雙向關聯關系時,應該在one方把inverse屬性設為true, 這可以提高性能。

在建立兩個對象的關聯時,應該同時修改關聯兩端的相應屬性,這樣才會使程式更加健壯,提高業務邏輯層的獨立性,使業務邏輯層的程式代碼

不受hibernate實作類的影響。同理,當删除雙向關聯的關系時,也應該修改關聯兩端的對象的相應屬性.

14.update 、saveorupdate、 meger差別與用法

<a>hibernate 的使用者曾要求一個既可自動配置設定新持久化辨別(identifier)儲存瞬時(transient)對象,又可更新/重新關聯脫管(detached)執行個體的通用方法。<code>saveorupdate()</code> 方法實作了這個功能。</a>

hibernate學習筆記(三)

<a></a>

<a><code>saveorupdate()</code> 用途和語義可能會使新使用者感到迷惑。首先,隻要你沒有嘗試在某個 session 中使用來自另一 session 的執行個體,你就應該不需要使用 <code>update()</code>, <code>saveorupdate()</code>,或 <code>merge()</code>。有些程式從來不用這些方法。</a>

<a>通常下面的場景會使用 <code>update()</code> 或 <code>saveorupdate()</code>:</a>

<a>程式在第一個 session 中加載對象</a>

<a>該對象被傳遞到表現層</a>

<a>對象發生了一些改動</a>

<a>該對象被傳回到業務邏輯層</a>

<a>程式調用第二個 session 的 <code>update()</code> 方法持久這些改動</a>

<a><code>saveorupdate()</code> 做下面的事:</a>

<a>如果對象已經在本 session 中持久化了,不做任何事</a>

<a>如果另一個與本 session 關聯的對象擁有相同的持久化辨別(identifier),抛出一個異常</a>

<a>如果對象沒有持久化辨別(identifier)屬性,對其調用 <code>save()</code></a>

<a>如果對象的持久辨別(identifier)表明其是一個新執行個體化的對象,對其調用 <code>save()</code>。</a>

<a>如果對象是附帶版本資訊的(通過 <code>&lt;version&gt;</code> 或 <code>&lt;timestamp&gt;</code>)并且版本屬性的值表明其是一個新執行個體化的對象,<code>save()</code> 它。</a>

<a>否則 <code>update()</code> 這個對象</a>

<a><code>merge()</code> 可非常不同:</a>

<a>如果 session 中存在相同持久化辨別(identifier)的執行個體,用使用者給出的對象的狀态覆寫舊有的持久執行個體</a>

<a>如果 session 沒有相應的持久執行個體,則嘗試從資料庫中加載(此處會有一次查詢),或建立新的持久化執行個體</a>

<a>最後傳回該持久執行個體</a>

<a>使用者給出的這個對象沒有被關聯到 session 上,它依舊是脫管的</a>