hibernate學習2

hibernate學習2

數據訪問 po(persistence object) 和 vo(value object)
vo就是簡單的值對象
po是值
1.納入hibernate管理框架中(entity map)的vo ,po的變化會在事務提交時將反應到實際數據庫中
2.hibernate返回的對象也是po
Hibernate_DEV_GUIDE.pdf
Hibernate_3.2.0_Reference_zh_CN.chm
session關閉 po就變成vo
從設計層面而言,應該避免直接po傳遞到系統中的其他層面,一種解決辦法是vo作爲DTO (data transfer object)
例子一:
userBean從數據庫加載,同時userBean對象的相關對象address也被加載,此時向userBean增加一個address對象
session.save(user),hibernate 會更具unsaved-value判斷哪些需要執行save操作。新增加滴地址id爲null,unsaved-value(null)相同,爲未保存對象將產生insert語句。“原有”關聯對象id和數據庫裏面一樣,unsaved-value(null) 不一樣,就不進行保存
inverse和cascade
inverse=“false” 爲主動方,由主動方負責維護關聯關係(一對多)
casecade級聯 對user進行save的時候 同時對address也執行save
延時加載
避免關聯關係帶來無味的性能開銷
session關閉後就獲取不到 user關聯對象的address的信息
那怎樣才能在session關閉後還能繼續加載user的關聯對象address的信息呢?
強制加載關聯對象實現 hibernate.initialize方法
hibernate爲了實現延時加載,對jdk的collection接口進行了獨立的實現。
所有編寫pojo的時候必須用jdk的 collection接口 如:set,map 而不能用jdk collect實現 hashSet HashMap等
這樣實現只有程序真正調用collection時,才激發底層實際的數據庫操作
事務管理jta 事務 和jdbc事務
//jdbc事務
session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//默認 AutoCommit=false
//如果 是下面語句 代碼將不會對數據庫產生任何效果
session.save(user);
session.close();
正確代碼如下:
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
session.close();
jta可以實現跨session的事務
jta可以跨越多個jdbc connection 生命週期
顯示聲明事務
UserTransaction tx = new InitialContext().lookup("....");

鎖(悲觀鎖、樂觀鎖)
悲觀鎖(將數據鎖定)對本系統其它事務和外部系統的事務處理持保守狀態,依靠數據庫提供的鎖機制,保證數據的排他性,否則本系統加鎖了,也不能保證外部系統不會修改數據
//一個典型的例子:
select * from t_user where name = "csy" for update
鎖住了 t_user表中說有 符合條件(name="csy")的記錄
 
String hqlStr = "from UserBean as user where user.name='csy'"
Query query = session.createQuery(hqlStr);
query.setLockMode("user,LockMode.UPGRADE");//加鎖
List userList = query.list();
樂觀鎖
悲觀鎖大部分是依靠數據庫的碩機制實現,以保證操作最大程度的獨佔性,這樣會使數據庫性能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受
 
樂觀鎖機制 大多數是基於數據版本(version),即爲數據增加一個版本標識,爲數據庫表增加一個“version”字段來實現
讀取數據的時候將此版本號一同讀出,之後更新時,對此版本號加一,判斷過期條件是:提交的數據版本號大於數據庫表當前版本號,者予以更新,否則認爲是過期數據
樂觀碩避免了長事務中的數據庫加鎖開銷 大大提高了併發量
 
樂觀碩的缺陷
外部系統對數據進行操作,不受我們系統的控制,因此可能會造成髒數據被更新到數據庫中。 在系統設計階段,進行調整(如將樂觀鎖策略在數據庫存儲過程中實現,對外開放的是存儲過程而不是數據庫表)
hibernate配置:
optimistic-lock="version"
hibernate 分頁
數據分頁顯示,不同的數據庫分頁模式往往各不相同,帶來了數據庫可移植的問題
hibernate 通過不同數據庫的統一接口設計
 
Criteria criteria = session.createCriteria(TUser.class);
criteria.add(Expression.eq("age","20"));
criteria.setFirstResult(100);
criteria.setFetchSize(20);
hibernate 通過不同的方言dialect來構造返回限定子句
如:mysql限定語句是limit 而oracle通過rownum句子來實現
cache管理
如果把數據在本地內存保存一個鏡像就會提高很多的效率
使用緩存需要考慮數據的有效性
1.我們系統於第三方系統共享數據庫的情況下,hibernate的cache機制可能失效(原因是 第三方系統對數據庫進行了更改,和ibernate並不知道數據庫中的數據已經發生了變化,也就是池中的數據還是修改之前的版本,hibernate會將此數據返回給上層代碼,有潛在問題)
2.統一系統中 基於hibernate和基於jdbc的兩中數據訪問方式並存

 
java的cache實現 最簡單的是hashTable 但是有性能實現
第三方cache實現
jcs EHCache OSCache \JBoss Cache \SwarmCache等
cache 分爲兩中
1.session級別的cache 屬於事務級別的緩衝 一旦事務結束 cache也就失敗,這爲內置實現,無需我們進行干涉
2.第二層cache 是對其實例範圍內的數據進行緩衝的管理,EHCache爲默認的第二級cache實現
但EHCache 不支持分佈式緩衝,如果我們的系統需要要在多臺設備上部署,並共享同一個數據庫必須使用分佈式緩衝的Cache如SwarmCache/JBossCache

其中SwarmCache提供的是invalidation方式的分佈式緩存,即當集羣中的某一個節點更新了緩存中的數據,即通知集羣中的其他節點將此數據廢除,之後各個節點需要用到這個數據的時候,會重新從數據庫中讀入並填充到緩存中
JBossCache 提供的是Reapplication式的緩衝,即如果集羣中某個節點的數據發生改變,此節點會將發生改變的數據的最新版本複製到集羣中的每個節點中以保持所有節點狀態一致
 
配置如下:
1.對ihibernate.cfg.xml配置
2.對EHCache進行配置
3.指定映射實體類的cache策略
<cache usage="read-write"/>
配置好後hibernate在運行期間會自動應用cache機制,也就是說。我們對po的更新,會自動同步到cache中
hibernate的查詢機制
 
Query.list();//產生一條select sql 獲取所有的記錄
Query.iterate();//產生一條select sql 獲取所有記錄的id ,通過id查詢所有的記錄。n+1條語句
區別
list不會從cache中取數據
iterate會更具id從cache中取數據
海量數據的時候使用iterate提高性能
session的管理
session中包含數據庫操作相關的狀態信息,對session的管理類似於jdbc的 jdbc Connection 的調度管理
避免session的頻繁的創建和銷燬 ,從而避免大量的內存開銷和頻繁的jvm回收
session的管理方案中,threadLocal模式得到了大量的使用
sessionFactory是線程安全的。
session不是線程安全的
ThreadLocal 的獨特之處就是會給每個線程維護一個私有的變量空間
實現原理是在jvm裏面維護一個map,map的key是當前線程對象,value是通過ThreadLocal.set方法保存的對象實例
可以通過過濾器來實現對session的管理
發佈了35 篇原創文章 · 獲贊 3 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章