主要分析三點:
二、單一主鍵映射和主鍵的生成策略 ;
三、復合主鍵的表映射 ;
Hibernate封裝了數據庫DDL語句,只需要將數據表和類之間實現映射,即可對數據表進行操作。
示例:數據庫中存在表interface_admin.ds_area,實現表和類之間映射,其中單一主鍵oggKeyId,使用主鍵自動生成策略UUID,具體第二點進行闡述 。
package com.pec.model; import java.io.Serializable; import java.sql.Timestamp; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; @Entity @Table(name = "interface_admin.ds_area") @org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true) public class DsAreaModel implements Serializable { private static final long serialVersionUID = 1L; //電商平台代號(WS微商/CT村淘/TM天貓/JD京東) private String comId ; //行政省/直轄市代號 private String provinceId ; //行政省/直轄市名稱 private String provinceName ; //地級市代號 private String cityId ; //地級市名稱 private String cityName ; //行政區/縣代號 private String regiId ; //行政區/縣名稱 private String regiName ; //創建時間 private Timestamp creatDate ; //最后更新時間 private Timestamp lastUpdDate ; //主鍵 private String oggKeyId ; @Column(name = "com_id") public String getComId() { return comId; } public void setComId(String comId) { this.comId = comId; } @Column(name = "province_id") public String getProvinceId() { return provinceId; } public void setProvinceId(String provinceId) { this.provinceId = provinceId; } @Column(name = "province_nm") public String getProvinceName() { return provinceName; } public void setProvinceName(String provinceName) { this.provinceName = provinceName; } @Column(name = "city_id") public String getCityId() { return cityId; } public void setCityId(String cityId) { this.cityId = cityId; } @Column(name = "city_nm") public String getCityName() { return cityName; } public void setCityName(String cityName) { this.cityName = cityName; } @Column(name = "regi_id") public String getRegiId() { return regiId; } public void setRegiId(String regiId) { this.regiId = regiId; } @Column(name = "regi_nm") public String getRegiName() { return regiName; } public void setRegiName(String regiName) { this.regiName = regiName; } @Column(name = "cre_date") public Timestamp getCreatDate() { return creatDate; } public void setCreatDate(Timestamp creatDate) { this.creatDate = creatDate; } @Column(name = "last_upd_date") public Timestamp getLastUpdDate() { return lastUpdDate; } public void setLastUpdDate(Timestamp lastUpdDate) { this.lastUpdDate = lastUpdDate; } @Id @Column(name = "ogg_key_id", unique = true, nullable = false) @GeneratedValue(generator = "systemUUID") @GenericGenerator(name = "systemUUID", strategy = "uuid") public String getOggKeyId() { return oggKeyId; } public void setOggKeyId(String oggKeyId) { this.oggKeyId = oggKeyId; } }
二、單一主鍵映射和主鍵的生成策略
當數據表中只存在單一主鍵(大多數情況下都是單一主鍵),主鍵標識着一條記錄,不可重復和為空,標志位唯一。但是此主鍵不需要手動輸入,而在Hibernate下包含有主鍵的生成策略。例如第一點的示例中:
@Id @Column(name = "ogg_key_id", unique = true, nullable = false) @GeneratedValue(generator = "systemUUID") @GenericGenerator(name = "systemUUID", strategy = "uuid") public String getOggKeyId() { return oggKeyId; } public void setOggKeyId(String oggKeyId) { this.oggKeyId = oggKeyId; }
此時,只需要在相應的setter的方法上,設置主鍵的生成策略(本例中為UUID)Hibernate即可自動生成唯一性標識,而省去了手動輸入的麻煩。使用Hibernate映射主鍵總結幾點:
1、為了保證對象標識符的唯一性與不可變性,應該讓Hibernate來為主鍵賦值,而不是程序。
2、Hibernate中唯一一種最簡單通用的主鍵生成器就是:UUID。雖然是個32位難讀的長字符串,但是它沒有跨數據庫的問題,將來切換數據庫極其簡單方便,推薦使用。
3、Hibernate下的UUID生成和Java下的UUID生成有所不同,Hibernate下是32位字長的16進制數,而Java下的則是36位字長。
4、其他主鍵的生成策略:assigned、increment、hilo、seqhilo、sequence、identity、native、guid、foreign、select。詳解參考:http://www.cnblogs.com/kakafra/archive/2012/09/16/2687569.html
三、復合主鍵的表映射 (出現情況不多,不推薦使用復合主鍵)
復合主鍵的情況是數據表存在多個主鍵,在實現與類映射時,情況比單一主鍵更加復雜。通常情況都會想法設法修改表結構成為單一主鍵,繞開復合主鍵,所以不推薦使用。但最近在做項目的時候,遇到表結構是復合主鍵,也無法繞開的情況,所以按此思路開始。這里我使用的是將主鍵屬性封裝在一個類當中,其中要注意的幾點:
1. 使用復合主鍵的實體類必須實現Serializable接口。
必須實現Serializable接口的原因很簡單,我們查找數據的時候是根據主鍵查找的。打開Hibernate的幫助文檔我們可以找到get與load方法的聲明形式如下: Object load(Class theClass,Serializable id) Object get(Class theClass,Serializable id) 當我們查找復合主鍵類的對象時,需要傳遞主鍵值給get()或load()方法的id參數,而id參數只能接收一個實現了Serializable接口的對象。而復合主鍵類的主鍵不是一個屬性可以表示的,所以只能先new出復合主鍵類的實例(例如:new People()),然后使用主鍵屬性的set方法將主鍵值賦值給主鍵屬性,然后將整個對象傳遞給get()或load()方法的id參數,實現主鍵值的傳遞,所以復合主鍵的實體類必須實現Serializable接口。 2. 使用復合主鍵的實體類必須重寫equals和hashCode方法。必須重寫equals和hashCode方法也很好理解。這兩個方法使用於判斷兩個對象(兩條記錄)是否相等的。為什么要判斷兩個對象是否相等呢?因為數據庫中的任意兩條記錄中的主鍵值是不能相同的,所以我們在程序中只要確保了兩個對象的主鍵值不同就可以防止主鍵約束違例的錯誤出現。也許這里你會奇怪為什么不使用復合主鍵的實體類不重寫這兩個方法也沒有主鍵違例的情況出現,這是因為使用單一主鍵方式,主鍵值是Hibernate來維護的,它會確保主鍵不會重復,而復合主鍵方式,主鍵值是編程人員自己維護的,所以必須重寫equals和hashCode方法用於判斷兩個對象的主鍵是否相同。 3. 重寫的equals和hashCode方法,只與主鍵屬性有關,普通屬性不要影響這兩個方法進行判斷。這個原因很簡單,主鍵才能決定一條記錄,其他屬性不能決定一條記錄。
4.主鍵類必須有默認的public無參數的構造方法。
實現復合主鍵映射的三種方式:
1、@Embeddable + @Id + @Embedded(@Embeddable 表示這個類可以嵌入到別的類中去,常以表示其他類的某個屬性。)
2、@Embeddable + @EmbeddedId( @Embedded 它和 @Embeddable 正好相反,它用來表示某個屬性是被嵌入進來的。) 3、@IdClass + @Id(@EmbeddedId = @Embedded + @Id)
以下貼出第一種方式的代碼:
主鍵類ModelKey:
package com.pec.model; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Embeddable; @Embeddable public class ModelKey implements Serializable{ private static final long serialVersionUID = 8099372586856509841L; // 接口類型 private String intType; // 條目識別碼 private String recordId; // private String createTimeStamp; public String getIntType() { return intType; } public void setIntType(String intType) { this.intType = intType; } public String getRecordId() { return recordId; } public void setRecordId(String recordId) { this.recordId = recordId; } public String getCreateTimeStamp() { return createTimeStamp; } public void setCreateTimeStamp(String createTimeStamp) { this.createTimeStamp = createTimeStamp; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((createTimeStamp == null) ? 0 : createTimeStamp.hashCode()); result = prime * result + ((intType == null) ? 0 : intType.hashCode()); result = prime * result + ((recordId == null) ? 0 : recordId.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; ModelKey other = (ModelKey) obj; if (createTimeStamp == null) { if (other.createTimeStamp != null) return false; } else if (!createTimeStamp.equals(other.createTimeStamp)) return false; if (intType == null) { if (other.intType != null) return false; } else if (!intType.equals(other.intType)) return false; if (recordId == null) { if (other.recordId != null) return false; } else if (!recordId.equals(other.recordId)) return false; return true; } public ModelKey(String intType, String recordId, String createTimeStamp) { this.intType = intType; this.recordId = recordId; this.createTimeStamp = createTimeStamp; } public ModelKey() { } }
實現類InterFaceDataModel:
package com.pec.model; import java.io.Serializable; import java.sql.Timestamp; import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; import javax.persistence.Column; import javax.persistence.Embedded; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.IdClass; import javax.persistence.Table; import org.hibernate.annotations.GenericGenerator; import com.sun.tracing.dtrace.Attributes; @Entity @Table(name = "interface_admin.interface_data_test") @org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true) //@IdClass(ModelKey.class) public class InterFaceDataModel implements Serializable{ private static final long serialVersionUID = 8586209694356988171L; private ModelKey modelKey ; private String seniorRecordId ; private Timestamp daleteTime ; private String createUser ; private String oprStatus ; private String oprUser ; private String oprTimeStamp ; private String yyyymmdd ; private String selKey1 ; private String selKey2 ; private String selKey3 ; private String selKey4 ; private String valList ; @Id @Embedded @AttributeOverrides({ @AttributeOverride(name="intType", column = @Column(name="int_type")), @AttributeOverride(name="recordId", column = @Column(name="record_id")), @AttributeOverride(name="createTimeStamp", column = @Column(name="create_timestamp")) }) public ModelKey getModelKey() { return modelKey; } public void setModelKey(ModelKey modelKey) { this.modelKey = modelKey; } @Column(name = "senior_record_id") public String getSeniorRecordId() { return seniorRecordId; } public void setSeniorRecordId(String seniorRecordId) { this.seniorRecordId = seniorRecordId; } @Column(name = "delete_time") public Timestamp getDaleteTime() { return daleteTime; } public void setDaleteTime(Timestamp daleteTime) { this.daleteTime = daleteTime; } @Column(name = "create_user") public String getCreateUser() { return createUser; } public void setCreateUser(String createUser) { this.createUser = createUser; } @Column(name = "opr_status") public String getOprStatus() { return oprStatus; } public void setOprStatus(String oprStatus) { this.oprStatus = oprStatus; } @Column(name = "opr_user") public String getOprUser() { return oprUser; } public void setOprUser(String oprUser) { this.oprUser = oprUser; } @Column(name = "opr_timestamp") public String getOprTimeStamp() { return oprTimeStamp; } public void setOprTimeStamp(String oprTimeStamp) { this.oprTimeStamp = oprTimeStamp; } @Column(name = "yyyymmdd") public String getYyyymmdd() { return yyyymmdd; } public void setYyyymmdd(String yyyymmdd) { this.yyyymmdd = yyyymmdd; } @Column(name = "sel_key1") public String getSelKey1() { return selKey1; } public void setSelKey1(String selKey1) { this.selKey1 = selKey1; } @Column(name = "sel_key2") public String getSelKey2() { return selKey2; } public void setSelKey2(String selKey2) { this.selKey2 = selKey2; } @Column(name = "sel_key3") public String getSelKey3() { return selKey3; } public void setSelKey3(String selKey3) { this.selKey3 = selKey3; } @Column(name = "sel_key4") public String getSelKey4() { return selKey4; } public void setSelKey4(String selKey4) { this.selKey4 = selKey4; } @Column(name = "val_list") public String getValList() { return valList; } public void setValList(String valList) { this.valList = valList; } }
具體參考鏈接:
http://blog.csdn.net/handsomelinux/article/details/50575877
http://www.cnblogs.com/otomedaybreak/archive/2012/01/25/2329390.html