国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Hibernate4-2 通過Session操縱對象

2019-11-08 02:03:45
字體:
來源:轉載
供稿:網友

  session接口是Hibernate向應用程序提供的操縱數據庫的最主要接口,其提供有基本的保存、更新、刪除和加載java對象的方法。   Session具有一個緩存,位于緩存中的對象稱為持久化對象,其與數據表中相關記錄相對應;其中,Session對象能夠在某些時間點,按照緩存中對象的變化來執行對應SQL語句,以同步更新數據庫,該過程被稱為刷新緩存(flush)。   站在持久化的角度來看,Hibernate將對象分為四種狀態:持久化狀態、臨時狀態、游離狀態和刪除狀態,Session的特定方法能使對象從一個狀態轉換到另一個狀態。


1. Session緩存

  概念:在Session接口的實現中包含一系列的Java集合,這些集合構成Session緩存。   **作用:**Session緩存可減少Hibernate應用程序訪問數據庫的頻率,因為只要Session實例沒有結束生命周期且沒有清理緩存,則存放在其緩存中的對象也不會消失。   其中,Session緩存的基本原理測試代碼如下所示:

// 注意:只會向數據庫發送一條SQL語句News news1 = (News) session.get(News.class, 1);System.out.PRintln(news1);News news2 = (News) session.get(News.class, 1);System.out.println(news2);System.out.println(news1 == news2); // true

1.1 flush緩存

  作用: Session按照緩存中對象的屬性變化來同步更新數據庫中的表記錄。   實現:刷新緩存的時間點為session.flush();transaction.commit()。   比較: Session對象的flush()方法可能會執行SQL語句,但不提交事務;而Transaction對象的commit()方法先調用flush()方法,再提交事務(將對數據庫的操作永久保存)。   設定刷新緩存的時間點:可以調用Session對象的setFlushMode()方法顯式設定刷新緩存的時間點,具體模式如下圖所示: 這里寫圖片描述   注意:在未提交事務或顯式調用Session對象flush()方法,也可能會進行緩存刷新操作,具體如下:

執行HQL或QBC查詢時:若緩存中持久化對象的屬性發生變化,則會先刷新緩存,以保證查詢結果能夠反映持久化對象的最新狀態;執行save()方法保存對象時:若對象使用native生成器生成OID,則執行保存操作時,會立即執行刷新操作以保證對象的ID是存在的。

1.2 refresh緩存

  作用:強制發送SELECT語句,以使Session緩存中對象的狀態和數據表中對應的記錄保持一致。   注意:MySQL數據庫的默認事務隔離級別為“REPEATABLE READ”,需要手動修改為“READ COMMITED”。

1.3 clear緩存

  作用:Session對象的clear()方法可以清除Session緩存中的所有緩存對象。


2. 數據庫的隔離級別

  數據庫的隔離性是指隔離并發運行各個事務的能力,而隔離級別是指一個事務與其他事務的隔離程度;隔離級別越高,數據一致性就越好,但并發性越弱。

2.1 并發問題概述

  對于同時運行的多個事務,當這些事務訪問數據庫中相同數據時,如果沒有采取必要的隔離機制,會導致各種并發問題,如下:

臟讀:對于兩個事務T1和T2,T1讀取了已經被T2更新但還沒有被提交的字段后,若T2回滾,T1讀取的內容就是臨時且無效的;不可重復讀:對于兩個事務T1和T2,T1讀取一個字段后,T2更新了該字段;之后T1再次讀取同一個字段時值發生變化;幻讀:對于兩個事務T1和T2,T1從一個表中讀取了一個字段后,T2在該表中插入一些新的行;之后,如果T1再次讀取同一個表,就會多出幾行。

2.2 事務隔離級別

  數據庫提供的四種事務隔離級別,分別是: 這里寫圖片描述   其中,Oracle 支持“READ COMMITED”(默認)和“SERIALIZABLE”兩種事務隔離級別,而MySQL支持四種事務隔離級別,默認為“READ COMMITED”。   

2.2 在MySQL中設置隔離級別

  在MySQL數據庫中,每啟動一個程序就會獲得一個單獨的數據庫連接,每個數據庫連接都有一個全局變量@@tx_isolation,表示當前的事務隔離級別。

查看當前的隔離級別:SELECT @@tx_isolation;設置當前MySQL連接的隔離級別:set transaction isolation level read committed;設置當前MySQL數據庫的隔離級別:set global transaction isolation level read committed

2.3 在Hibernate中設置隔離級別

  JDBC數據庫連接使用數據庫系統默認的隔離級別。在Hibernate中可通過配置其hibernate.connection.isolation屬性的方式來設置事務的隔離級別,具體說明如下:

<!-- 1). 配置數據庫的事務隔離級別為:READ UNCOMMITED --><property name="hibernate.connection.isolation">1</property><!-- 2). 配置數據庫的事務隔離級別為:READ COMMITED --><property name="hibernate.connection.isolation">2</property><!-- 3). 配置數據庫的事務隔離級別為:REPEATABLE READ --><property name="hibernate.connection.isolation">4</property><!-- 4). 配置數據庫的事務隔離級別為:SERIALIZEABLE --><property name="hibernate.connection.isolation">8</property>

3. 持久化對象的狀態

  站在持久化的角度,Hibernate把對象分為四種狀態:持久化狀態、臨時狀態、游離狀態、刪除狀態;Session的特定方法能使對象從一個狀態轉換到另一個狀態。

3.1 臨時對象(Transient)

在使用代理主鍵的情況下,OID通常為null;不處于Session緩存中;在數據庫中沒有對應的記錄。

3.2 持久化對象(Persist)

OID不為null;位于Session緩存中;若在數據庫中已經有與其對應的記錄,持久化對象和數據庫中的相關記錄對應;Session 在flush緩存時,會根據持久化對象的屬性變化,來同步更新數據庫;在同一個Session實例的緩存中, 數據庫表中每條記錄只對應唯一的持久化對象。

3.3 刪除對象(Removed)

在數據庫中沒有和其OID對應的記錄;不再處于Session緩存中;一般情況下,應用程序不該再使用被刪除的對象。

3.4 游離對象(Detached)

OID不為null;不再處于Session緩存中;一般情況下,游離對象是由持久化對象轉變而來,在數據庫中可能還存在與其對應的記錄。

3.5 對象狀態轉換圖

這里寫圖片描述


4. Session核心方法

4.1 save()與persist()方法

/** * Session對象的save()方法: * 1). 將臨時對象加入Session緩存中,使其轉變為持久化對象; * 2). 選用映射文件指定的標識符生成器,為持久化對象分配唯一的OID; * 3). 在flush緩存時,會發送一條INSERT語句; * 4). 在使用代理主鍵的情況下,通過setId()方法為臨時對象設置OID是無效的; * 5). 持久化對象的OID不能被隨意修改,因其維持著持久化對象與數據庫記錄的對應關系。 * * Session對象的persist()方法:也會執行INSERT操作; * 與save()方法的不同之處:當臨時對象的OID不為空時,該方法將拋出異常。 */@Testpublic void testSaveAndPersist() { News news = new News(null, "qiaobc", "qiaobei", new Date()); news.setId(1001); // 為臨時對象設置OID是無效的 System.out.println(news); // session.persist(news); session.save(news); System.out.println(news); // news.setId(1002); // 持久化對象的OID不能修改}

4.2 get()與load()方法

/** * Session對象的get()與load()方法:均可根據OID從數據庫中加載一個持久化對象 * 1). 執行get()方法時,立即加載對象; * 而執行load()方法時,延遲加載對象,即若不使用該對象,則不會立即查詢,而是返回一個代理對象; * 2). load()方法可能會拋出LazyInitializationException異常:在需要初始化代理對象前關閉Session對象; * 3). 若數據表中沒有與OID對應的記錄,則get()方法返回null; * 而load()方法,若不使用該對象的任何屬性則沒問題,若需要初始化則拋出ObjectNotFoundException異常。 */@Testpublic void testGet() { News news1 = (News) session.get(News.class, 10); System.out.println(news1); // 持久化狀態 session.close(); // 游離狀態 System.out.println(news1);}@Testpublic void testLoad() { News news2 = (News) session.load(News.class, 1); // 若不使用,則返回代理對象com.qiaobc.hibernate.entities.News_$$_javassist_0 System.out.println(news2.getClass().getName()); session.close(); // 游離狀態 System.out.println(news2); // 拋出LazyInitializationException異常}

4.3 update()方法

/** * Session對象的update()方法: * 1). 更新持久化對象不需要顯式調用update()方法,因為事務提交時會flush緩存; * 2). 更新游離對象需要顯式調用update()方法,將其轉變為持久化對象; * * 注意: * 1). 無論要更新的游離對象和數據表的記錄是否一致,均會發送UPDATE語句; * 當Hibernate與觸發器協同工作時,可在*.hbm.xml文件的class節點 * 設置select-before-update=true以確保不盲目發送UPDATE語句; * 2). 當 update()方法關聯一個游離對象時,如果在數據庫中不存在相應的記錄,拋出異常; * 3). 當 update()方法關聯一個游離對象時,如果在Session緩存中已經存在相同OID的持久化對象,拋出異常; */@Testpublic void update1() { News news = (News) session.get(News.class, 1); news.setAuthor("SUN"); session.update(news); // 若更新持久化對象不需要顯式調用update()方法}@Testpublic void update2() { News news = (News) session.get(News.class, 1); transaction.commit(); session.close(); session = sessionFactory.openSession(); transaction = session.beginTransaction(); news.setAuthor("SUN"); // 此時news為游離對象 session.update(news); }

4.4 saveOrUpdate()方法

/** * Session對象的saveOrUpdate()方法:臨時對象執行保存操作,游離對象執行更新操作。 * 1). 判定對象為臨時對象的標準:Java對象的OID是否為null; * 2). 了解:若Java對象的OID取值等于映射文件中id節點unsaved-value屬性值,則其也為臨時對象。 */@Testpublic void testSaveOrUpdate() { // OID不為空,執行更新操作;若OID對應的記錄不存在,則拋出StaleStateException異常。 News news1 = new News(10, "qiaobc1", "qiaobei1", new Date()); session.saveOrUpdate(news1); // OID為空,執行保存操作 News news2 = new News(null, "qiaobc", "qiaobei", new Date()); session.saveOrUpdate(news2);}

4.5 merge()方法

這里寫圖片描述

4.6 delete()方法

/** * Session對象的delete()方法:既可以刪除一個游離對象,也可以刪除一個持久化對象 * 1). 只要OID與數據表中記錄對應,即執行刪除操作;無對應記錄則拋出異常; * 2). 通過設置hibernate.use_identifier_rollback=true,使刪除對象時置OID=null; */@Testpublic void testDelete() { News news = new News(); news.setId(5); session.delete(news); // 刪除游離對象 News news2 = (News) session.get(News.class, 6); session.delete(news2); // 刪除持久化對象 // 配置前:News [id=6, title=qiaobc, author=qiaobei, date=2017-02-20 17:10:35.0] // 配置后:News [id=null, title=qiaobc, author=qiaobei, date=2017-02-20 17:10:35.0] System.out.println(news2);}

4.7 evict()方法

/** * Session對象的evict()方法:從緩存中將持久化對象移除 */@Testpublic void testEvict() { News news1 = (News) session.get(News.class, 1); News news2 = (News) session.get(News.class, 2); news1.setAuthor("No.1"); news2.setAuthor("No.2"); session.evict(news2); // 移除news2對象,不再更新該對象}

5. Hibernate調用存儲過程

這里寫圖片描述


6. Hibernate與觸發器協同工作

這里寫圖片描述


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 文水县| 浑源县| 木兰县| 三门县| 双柏县| 金门县| 百色市| 玉龙| 吉木乃县| 克东县| 荣成市| 磴口县| 奉节县| 福鼎市| 韶关市| 辉南县| 巍山| 赞皇县| 巴东县| 澎湖县| 寻甸| 临澧县| 会东县| 兴海县| 涟水县| 蒙山县| 大悟县| 衡山县| 永康市| 遵义县| 南靖县| 峡江县| 河池市| 民权县| 南宁市| 安多县| 托克逊县| 丹阳市| 稻城县| 建阳市| 武胜县|