概述Hibernate equals()方法
在向大家詳細介紹Hibernate equals()方法之前,首先讓大家了解下Java應(yīng)用程序,然后全面介紹Hibernate equals()方法。
當(dāng)對象持久化到數(shù)據(jù)庫中時,對象的標(biāo)識符總時很難被恰當(dāng)?shù)膶崿F(xiàn)。盡管如此,問題其實完全是由存在著在保存之前不持有ID的對象的現(xiàn)象衍生而來的。我們可以通過從諸如Hibernate這樣的對象—關(guān)系映像框架手中取走指派對象ID的職責(zé)來解決這個問題。相對的,一旦對象被實例化,它就應(yīng)該被指派一個ID.這使對象標(biāo)識符變成簡單而不易出錯,也減少了領(lǐng)域模型中需要的代碼量。
企業(yè)級Java應(yīng)用程序常常把數(shù)據(jù)在java對象和關(guān)系型數(shù)據(jù)庫之間來回移動。從手動編寫SQL代碼到使用諸如Hibernate這樣的成熟的對象——關(guān)系映像(ORM)解決方案,有很多種方法可以實現(xiàn)這個過程。無論你采用什么樣的技術(shù),一旦你開始將java對象持久化到數(shù)據(jù)庫中,對象標(biāo)識符都將成為一個復(fù)雜而且難以管理的課題。可能出現(xiàn)的情況是:你實例化了兩個不同的對象,而它們卻代表了數(shù)據(jù)庫中的同一行。為了解決這個問題,你可能采取的措施是在你的持久化對象中實現(xiàn)equals() 和hashCode()這兩個方法,可是要恰當(dāng)?shù)膶崿F(xiàn)這兩個方法比乍看之下要有技巧一些。讓問題更糟糕的是,那些傳統(tǒng)的思路(包括Hibernate官方文檔所提倡的那些)對于新的工程并不一定能提出最實用的解決方案。
對象標(biāo)識在虛擬機(VM)中和在數(shù)據(jù)庫中的差異是問題滋生的溫床。在虛擬機中,你并不會得到對象的id,你只是簡單的持有對象的直接引用。而在幕后,虛擬機確實給每個對象指派了一個8字節(jié)大小的id,這個id才是對象的真實引用。當(dāng)你將對象持久化到數(shù)據(jù)庫中的時候,問題開始產(chǎn)生了。假定你創(chuàng)建了一個 Person對象并將它存入數(shù)據(jù)庫(我們可以叫它person1)。而你的其它某段代碼從數(shù)據(jù)庫中讀取了這個Person對象的數(shù)據(jù)并將它實例化為另一個新的Person對象(我們可以叫它Person2)?,F(xiàn)在你的內(nèi)存中有了兩個映像到數(shù)據(jù)庫中同一行的對象。一個對象引用只能指向它們倆的其中一個,可是我們需要一種方法來表示這兩個對象實際上表示著同一個實體。這就是(在虛擬機中)引入對象標(biāo)識符的原因。
在java語言中,對象標(biāo)識符是由每個對象都持有的Hibernate equals()方法(以及相關(guān)的hashCode()方法)來定義的。無論兩個對象(引用)是否為同一個實例,Hibernate equals()方法都應(yīng)該能夠判別出它們是否表示同一個實體。hashCode()方法和Hibernate equals()方法有關(guān)聯(lián)是因為所有被判斷等價(equal)的對象都應(yīng)該返回相同的哈希值(hashCode)。在缺省實現(xiàn)中,Hibernate equals()方法僅僅比較對象的引用,一個對象和它自身是等價的,而和其它任何實例都不等價。對于持久化對象來說,重寫這兩個方法,讓代表著數(shù)據(jù)庫中同一行的兩個對象被判為等價是很重要的。而這對于java中的Collection數(shù)據(jù)結(jié)構(gòu)(Set,Map和List)的正確工作更是尤為重要。
為了闡明實現(xiàn)equal()和hashCode()的不同途徑,讓我們一起考慮一個準(zhǔn)備持久化到數(shù)據(jù)庫中的簡單對象Person.
- public class Person {
- private Long id;
- private Integer version;
- public Long getId() { return id; }
- public void setId(Long id) {
- this.id = id;
- }
- public Integer getVersion() {
- return version;
- }
- public void setVersion(Integer version) {
- this.version = version;
- }
- // person-specific properties and behavior
- }
在這個例子中,我們遵循了同時持有id字段和version字段的最佳實踐。Id字段保存了在數(shù)據(jù)庫中作為主鍵使用的值,而version字段則是一個從0開始增長的增量,隨著對象的每次更新而變化(它幫助我們避免并發(fā)更新的問題)。為了看的更清楚,我們也一起看一下Hibernate把這個對象持久化到數(shù)據(jù)庫的映像文件。
- <?XML version="1.0"?>
- <hibernate-mapping package="my.package">
- <class name="Person" table="PERSON">
- <id name="id" column="ID" unsaved-value="null">
- <generator class="sequence">
- <param name="sequence">PERSON_SEQ</param>
- </generator>
- </id>
- <version name="version" column="VERSION" />
- <!-- Map Person-specific properties here. -->
- </class>
- </hibernate-mapping>
【編輯推薦】