熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

別讓Hibernate偷走了你的標識符[5]

2013-11-23 20:43:25  來源: Java開源技術 

  Person類現在就簡單多了

public class Person extends AbstractPersistentObject { // Personspecific fields and behavior here}

  從上一個例子開始Hibernate映像文件就不會再改變了我們不想麻煩Hibernate去了解抽象父類相對的我們只要保證每個持久化對象的映射文件包含一個id項(和一個被指派的生成器)和一個帶有unsavedvalue=null屬性的version標簽機敏的讀者可能已經注意到每當一個持久化對象被實例化的時候它的id值得到了指派這意味著當Hibernate在內存中創建一個已經保存過的對象時雖然這個對象是已經存在並從數據庫中讀取的它也會得到一個新的id這不會產生問題因為Hibernate會接著調用對象的setId()方法用保存的真實id來替換新分配的id剩下的id生成器並不是問題因為實現它的算法是輕量級的(也就是說它並不牽扯到數據庫)

  到現在為止一切都很好但是我們遺漏了一個重要的細節如何實現IdGeneratorcreateId()我們可以為我們理想中的鍵值生成器(keygeneration)算法定義一些標准

  ● 鍵值可以不牽扯到數據庫而很輕量級的產生

  ● 即使跨越不同的虛擬機和不同機器鍵值也要保證唯一性

  ● 如果可能鍵值可以由其它程序編程語言和數據庫生成至少要能和它們兼容

  我們需要的是通用唯一標識符(UUID)UUID是由標准格式化的個字節大小的(位)數字組成的UUID的字符串版本是像這樣的
cdbceefdacaec(大家應該可以注意到 Jmatrix目前就是使用的UUID)

  裡面的字符是數字簡單的按字節的進制表示橫線把數字的不同部分分割開來這種格式簡單而且易於處理只是個字符有點兒太長了因為橫線總是被安置在相同的位置所以可以把它們去掉而把字符的數目減少到用一種更為簡潔的表示方法你可以創建一個byte[]的數組或是兩個字節大小的長整型(long)來保存這些數字如果你使用的是Java或更高版本你可以直接使用UUID類雖然這不是它在內存中最簡潔的格式如果你要獲得更多的信息請參閱Wikipedia 的UUID條目 或 Java UUID參考文檔

  對UUID的產生算法有多種實現既然最終UUID是一種標准格式我們在IdGenerator類中采用哪一種實現都沒有關系既然無論采用什麼算法每個id都會被保證唯一我們甚至可以在任何時候改變算法的實現或是混合匹配不同的實現如果你使用的是java或更高版本最方便的實現是javautilUUID類

public class IdGenerator {
 public static String createId() {
UUID uuid = javautilUUIDrandomUUID();
return uuidtoString();
 }
}

  對不使用java或更高版本的人來說至少有兩種擴展庫實現了UUID並且和之前的java版本兼容 Apache Commons ID project 和 Java UUID Generator(JUG) project它們都在Apache的旗下(在LGPL之下JUG也是可用的)

  這是使用JUG庫實現IdGenerator的例子

import orgsafehausuuidUUIDGenerator;
public class IdGenerator {
 public static final UUIDGenerator uuidGen = UUIDGeneratorgetInstance();
 public static String createId() {
UUID uuid = uuidGengenerateRandomBasedUUID();
return uuidtoString();
 }
}

  Hibernate內置的UUID生成器算法又如何呢?這是一個得到驗證對象標識用的UUID的適當途徑嗎?如果你想讓對象標識符獨立於對象的持久化這就不是一個好方法雖然Hibernate確實提供有讓它為你生成UUID的選項但這樣的話我們又回到了那個最早的問題上對象ID的獲得並不在它們被創建的時候而在它們被保存的時候

  使用UUID作為數據庫主鍵的最大障礙是它們在數據庫中(而不是在內存中)的大小在數據庫中索引和外鍵的復合會促使主鍵大小的增加你必須在不同的情況下使用不同的表示方法使用String表示數據庫的主鍵大小將會是字節Id也可以直接使用位存儲這樣將減少一半的占用空間但是如果你直接查詢數據庫id將變得難以理解這些方法對你的工程是否可行取決於你的需求 如果你的數據庫不接受UUID作為主鍵你可以考慮使用數據庫序列但總是應該讓新對象創建的時候被指派一個ID而不是讓Hibernate管理你的ID在這種情況下創建新的域對象的商業對象可以調用一個使用data Access object(DAO)從數據庫序列中獲取數據庫id的服務如果你使用一個長整型來表示你的對象id一個單獨的數據庫序列(以及服務方法)對你的域對象來說已經足夠了

  小結

  當對象持久化到數據庫中時對象的標識符總時很難被恰當的實現盡管如此問題其實完全是由存在著在保存之前不持有ID的對象的現象衍生而來的我們可以通過從諸如Hibernate這樣的對象—關系映像框架手中取走指派對象ID的職責來解決這個問題相對的一旦對象被實例化它就應該被指派一個ID這使對象標識符變成簡單而不易出錯也減少了領域模型中需要的代碼量

[]  []  []  []  []  


From:http://tw.wingwit.com/Article/program/Java/ky/201311/28966.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.