如果表使用聯合主鍵(一個表有兩個以上的主鍵),你可以映射類的多個屬性為標識符屬性。如:<composite-id>元素接受<key-property> 屬性映射(單表映射)和<key-many-to-one>屬性映射作為子元素(多表映射)。
<composite-id>
<key-property name="stationNum" type="java.lang.String" column="STATIONNUM"/>
<key-property name="observTimes" type="java.util.Date" column="OBSERVTIMES"/>
</composite-id>
在持久化類必須重載equals()和hashCode()方法,來實現組合的標示符的相等判斷,實現Serializable接口也是必須的。
不幸的是,這種組合關鍵字的方法意味着一個持久化類是它自己的標識。除了對象自己之外, 沒有什么方便的“把手”可用。你必須初始化持久化類的實例,填充它的標識符屬性,再load() 組合關鍵字關聯的持久狀態。我們把這種方法稱為embedded(嵌入式)的組合標識符,在重要的應用中不鼓勵使用這種用法。
第二種方法我們稱為mapped(映射式)組合標識符 (mapped composite identifier),<composite-id>元素中列出的標識屬性不但在持久化類出現,還形成一個獨立的標識符類。
<composite-id name="id" class="hibernate.RainId">
<key-property name="stationNum" type="string">
<column name="StationNum" length="5" />
</key-property>
<key-property name="observTimes" type="timestamp">
<column name="ObservTimes" length="19" />
</key-property>
</composite-id>
在這個例子中,組合標示符類RainId和實體類都含有stationNum和observTimes屬性,標示符必須重載equals()和hashCode()並且實現Serializable接口。這種方法的缺點是出現了明顯的代碼重復。
<key-property name="stationNum" type="java.lang.String" column="STATIONNUM"/>
<key-property name="observTimes" type="java.util.Date" column="OBSERVTIMES"/>
</composite-id>
在持久化類必須重載equals()和hashCode()方法,來實現組合的標示符的相等判斷,實現Serializable接口也是必須的。
不幸的是,這種組合關鍵字的方法意味着一個持久化類是它自己的標識。除了對象自己之外, 沒有什么方便的“把手”可用。你必須初始化持久化類的實例,填充它的標識符屬性,再load() 組合關鍵字關聯的持久狀態。我們把這種方法稱為embedded(嵌入式)的組合標識符,在重要的應用中不鼓勵使用這種用法。
第二種方法我們稱為mapped(映射式)組合標識符 (mapped composite identifier),<composite-id>元素中列出的標識屬性不但在持久化類出現,還形成一個獨立的標識符類。
<composite-id name="id" class="hibernate.RainId">
<key-property name="stationNum" type="string">
<column name="StationNum" length="5" />
</key-property>
<key-property name="observTimes" type="timestamp">
<column name="ObservTimes" length="19" />
</key-property>
</composite-id>
在這個例子中,組合標示符類RainId和實體類都含有stationNum和observTimes屬性,標示符必須重載equals()和hashCode()並且實現Serializable接口。這種方法的缺點是出現了明顯的代碼重復。
下面列出的屬性是用來指定一個映射式組合標識符的:
mapped (可選, 默認為false): 指明使用一個映射式組合標識符,其包含的屬性映射同時在實體類和組合標識符類中出現。
class (可選,但對映射式組合標識符必須指定): 作為組合標識符類使用的類名.
name (可選,但對這種方法而言必須): 包含此組件標識符的組件類型的名字.
access (可選 - 默認為property):
hibernate應該使用的訪問此屬性值的策略
hibernate應該使用的訪問此屬性值的策略
class (可選 - 默認會用反射來自動判定屬性類型 ): 用來作為組合標識符的組件類的類名
第三種方式,被稱為identifier component(標識符組件)是我們對幾乎所有應用都推薦使用的方式。
例子:
POJO類
public class Rain implements java.io.Serializable {
private RainId id;//聯合主鍵
private Date insertTimes;
private Integer precipitation;
private Integer threePrecip;
private Integer sixPrecip;
private Integer twelvePrecip;
private Integer twentyFourPrecip;
private Integer minuteRain0;
private Integer minuteRain1;
聯合主鍵bean
public class RainId implements java.io.Serializable {
private String stationNum;
private Date observTimes;
public RainId() {
}
public RainId(String stationNum, Date observTimes) {
this.stationNum = stationNum;
this.observTimes = observTimes;
}
例子:
POJO類
public class Rain implements java.io.Serializable {
private RainId id;//聯合主鍵
private Date insertTimes;
private Integer precipitation;
private Integer threePrecip;
private Integer sixPrecip;
private Integer twelvePrecip;
private Integer twentyFourPrecip;
private Integer minuteRain0;
private Integer minuteRain1;
聯合主鍵bean
public class RainId implements java.io.Serializable {
private String stationNum;
private Date observTimes;
public RainId() {
}
public RainId(String stationNum, Date observTimes) {
this.stationNum = stationNum;
this.observTimes = observTimes;
}
//重寫equals 和hashcode方法
public boolean equals(Object other) {
if ((this == other))
return true;
if ((other == null))
return false;
if (!(other instanceof RainId))
return false;
RainId castOther = (RainId) other;
return ((this.getStationNum() == castOther.getStationNum()) || (this
.getStationNum() != null && castOther.getStationNum() != null && this
.getStationNum().equals(castOther.getStationNum())))
&& ((this.getObservTimes() == castOther.getObservTimes()) || (this
.getObservTimes() != null
&& castOther.getObservTimes() != null && this
.getObservTimes().equals(castOther.getObservTimes())));
}
public int hashCode() {
int result = 17;
result = 37
* result
+ (getStationNum() == null ? 0 : this.getStationNum()
.hashCode());
result = 37
* result
+ (getObservTimes() == null ? 0 : this.getObservTimes()
.hashCode());
return result;
}
if ((this == other))
return true;
if ((other == null))
return false;
if (!(other instanceof RainId))
return false;
RainId castOther = (RainId) other;
return ((this.getStationNum() == castOther.getStationNum()) || (this
.getStationNum() != null && castOther.getStationNum() != null && this
.getStationNum().equals(castOther.getStationNum())))
&& ((this.getObservTimes() == castOther.getObservTimes()) || (this
.getObservTimes() != null
&& castOther.getObservTimes() != null && this
.getObservTimes().equals(castOther.getObservTimes())));
}
public int hashCode() {
int result = 17;
result = 37
* result
+ (getStationNum() == null ? 0 : this.getStationNum()
.hashCode());
result = 37
* result
+ (getObservTimes() == null ? 0 : this.getObservTimes()
.hashCode());
return result;
}
配置映射文本 hbm.xml
<class name="hibernate.Rain" table="rain" catalog="base">
<composite-id name="id" class="hibernate.RainId">
<key-property name="stationNum" type="string">
<column name="StationNum" length="5" />
</key-property>
<key-property name="observTimes" type="timestamp">
<column name="ObservTimes" length="19" />
</key-property>
</composite-id>
<property name="insertTimes" type="timestamp">
<column name="InsertTimes" length="19" />
</property>
<class name="hibernate.Rain" table="rain" catalog="base">
<composite-id name="id" class="hibernate.RainId">
<key-property name="stationNum" type="string">
<column name="StationNum" length="5" />
</key-property>
<key-property name="observTimes" type="timestamp">
<column name="ObservTimes" length="19" />
</key-property>
</composite-id>
<property name="insertTimes" type="timestamp">
<column name="InsertTimes" length="19" />
</property>
缺點:
1、聯合主鍵當中的字段不應該存在空值
在實際的開發當中我發現,如果聯合主鍵中的某一字段為空值,那么將會導致通過該聯合主鍵查詢出來的結果為空值,這個問題不知道是hibernate的bug還是spring集成hibernate時產生的問題,總之在實際使用的時候最好保證作為聯合主鍵的字段都是有值的。
2、主鍵容易沖突
hibernate聯合主鍵的另一個弊端就是存在主鍵重復的隱患,如果將某幾個字段做為聯合主鍵,在這些字段更新之后很可能造成重復,但數據庫中並不會報錯(存在其他不相同的字段),然而hibernate卻會報主鍵重復的錯誤。
在實際的開發當中我發現,如果聯合主鍵中的某一字段為空值,那么將會導致通過該聯合主鍵查詢出來的結果為空值,這個問題不知道是hibernate的bug還是spring集成hibernate時產生的問題,總之在實際使用的時候最好保證作為聯合主鍵的字段都是有值的。
2、主鍵容易沖突
hibernate聯合主鍵的另一個弊端就是存在主鍵重復的隱患,如果將某幾個字段做為聯合主鍵,在這些字段更新之后很可能造成重復,但數據庫中並不會報錯(存在其他不相同的字段),然而hibernate卻會報主鍵重復的錯誤。