在現實中咱們可能會遇到許多表多是沒有主鍵的,那麼咱們對其作映射後使用會是什麼樣的結果?能正常獲得咱們想要的嗎?結果應該是得不到想要的結果,而獲得的可能會是以下的報錯:java
Caused by:org.hibernate.AnnotationException: No identifier specified for entity: xxx.xxx.xxxide
這個結果告訴咱們:Hibernate映射表是須要主鍵的。測試
因此複合主鍵映射就應運而生了。this
複合主鍵使用一個可嵌入的類做爲主鍵表示,所以你須要使用@Id和@Embeddable兩個註解.還有一種方式是使用@EmbeddedId註解.固然還有一種方法那就是——使用@IdClass註解。具體請查看【hibernate-annotations-3.4.0.GA 2.2.6.映射覆合主鍵與外鍵】。spa
固然,只須要選擇其中的一種就能夠了。^_^.net
注意所依賴的類必須實現 serializable以及實現equals()/hashCode()方法.hibernate
舉一個具體事例:code
package com.sourcefour.bean; // default package import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverrides; import javax.persistence.Column; import javax.persistence.EmbeddedId; import javax.persistence.Entity; import javax.persistence.Table; /** * User entity. @author MyEclipse Persistence Tools */ @Entity @Table(name="t_user_composite_pk" ) public class User implements java.io.Serializable { // Fields private UserId id; // Constructors /** default constructor */ public User() { } /** full constructor */ public User(UserId id) { this.id = id; } // Property accessors @EmbeddedId @AttributeOverrides( { @AttributeOverride(name="intId", column=@Column(name="intId", nullable=false) ), @AttributeOverride(name="varcName", column=@Column(name="varcName", length=50) ), @AttributeOverride(name="varcAddress", column=@Column(name="varcAddress", length=50) ), @AttributeOverride(name="intAge", column=@Column(name="intAge", nullable=false) ) } ) public UserId getId() { return this.id; } public void setId(UserId id) { this.id = id; } }
2.2. UserId.javablog
package com.sourcefour.bean; // default package import javax.persistence.Column; import javax.persistence.Embeddable; /** * UserId entity. @author MyEclipse Persistence Tools */ @Embeddable public class UserId implements java.io.Serializable { // Fields private int intId; private String varcName; private String varcAddress; private int intAge; // Constructors /** default constructor */ public UserId() { } /** minimal constructor */ public UserId(int intId, int intAge) { this.intId = intId; this.intAge = intAge; } /** full constructor */ public UserId(int intId, String varcName, String varcAddress, int intAge) { this.intId = intId; this.varcName = varcName; this.varcAddress = varcAddress; this.intAge = intAge; } // Property accessors @Column(name = "intId", nullable = false) public int getIntId() { return this.intId; } public void setIntId(int intId) { this.intId = intId; } @Column(name = "varcName", length = 50) public String getVarcName() { return this.varcName; } public void setVarcName(String varcName) { this.varcName = varcName; } @Column(name = "varcAddress", length = 50) public String getVarcAddress() { return this.varcAddress; } public void setVarcAddress(String varcAddress) { this.varcAddress = varcAddress; } @Column(name = "intAge", nullable = false) public int getIntAge() { return this.intAge; } public void setIntAge(int intAge) { this.intAge = intAge; } public boolean equals(Object other) { if ((this == other)) return true; if ((other == null)) return false; if (!(other instanceof UserId)) return false; UserId castOther = (UserId) other; return (this.getIntId() == castOther.getIntId()) && ((this.getVarcName() == castOther.getVarcName()) || (this.getVarcName() != null && castOther.getVarcName() != null && this.getVarcName().equals(castOther.getVarcName()))) && ((this.getVarcAddress() == castOther.getVarcAddress()) || (this.getVarcAddress() != null && castOther.getVarcAddress() != null && this.getVarcAddress().equals( castOther.getVarcAddress()))) && (this.getIntAge() == castOther.getIntAge()); } public int hashCode() { int result = 17; result = 37 * result + this.getIntId(); result = 37 * result + (getVarcName() == null ? 0 : this.getVarcName().hashCode()); result = 37 * result + (getVarcAddress() == null ? 0 : this.getVarcAddress().hashCode()); result = 37 * result + this.getIntAge(); return result; } }
3. 可能還會出現的問題ip
具體來講問題就是查詢出來的結果列表爲‘null’(這一點我此次在我機器上測試時沒有出現)。
若是出現了該問題,那麼看到這一點就應該能解決問題啦,若是不出現那就更好,呵呵!
可是我的以爲這一點應該仍是得說的。^_^
有時候查詢出來的結果列表爲‘null’,這使人非常費解,能夠想下這是什麼緣由?
直接上緣由,嘎嘎……。
緣由:做爲聯合主鍵的字段理論上不該該包含可能爲空的字段。
緣由分析:根據緣由,說明實體Bean中的某個(些)對應的表字段有空值。
解決方案:只須要將可能爲空的字段不做爲聯合主鍵的一部分就能夠。
說的估計暈頭了吧,直接來個事例吧(我的一直以爲,例子是解釋問題的最好說明)。
假設表中的varcName和varcAddress是可能爲空的,其它都不可能爲空,那麼映射應該是這樣的
User.java
…… private UserId id; private String varcName; private String varcAddress; …… /* 這裏加入varcName和varcAddress映射內容,嗯仍是貼出來吧,反正電子檔的又不怕木有地方,嘎嘎…… */ @Column(name="varcName", length=50) public String getVarcName() { return this.varcName; } public void setVarcName(String varcName) { this.varcName = varcName; } @Column(name="varcAddress", length=50) public String getVarcAddress() { return this.varcAddress; } public void setVarcAddress(String varcAddress) { this.varcAddress = varcAddress; }
UserId.java