上一篇博客簡單介紹了SpringData JPA實現簡單的CRUD,分頁與多條件的排序,那里的主鍵類型是Long,有時我們會遇到主鍵不是一個的,復合主鍵,經過調研如下。確定一個人,不能只根據他的姓名來確定,因為會有重名,現在我們假設姓名、身份證號確定唯一一個人。
復合主鍵:一張表存在多個字段共同組成一個主鍵,這多個字段的組合不能重復,但是單獨一個可以重復。
例子:姓名和省份證號共同組成了主鍵
一、Spring Data Jpa 復合主鍵
1.1、編寫一個復合主鍵類:PeopleKey
@Embeddable public class PeopleKey implements Serializable { @Column(name = "name") private String name; @Column(name = "idcardno") private String idcardno; // 省略setter,getter方法 @Override public String toString() { return "PeopleKey [name=" + name + ", idcardno=" + idcardno + "]"; } }
注意:
1) 實現Serializable
接口(否則會報錯,錯誤會直接顯示);
2)在復合主鍵的類上,使用注解@Embeddable
3) 有默認的public無參數的構造方法(在我這個實例中,我沒有添加有參構造方法,所以采用默認的構造方法)
如果你在實體類里有有參構造方法,那么一定要有一個無參構造方法,否則運行的時候會報錯
org.hibernate.InstantiationException: No default constructor for entity: : com.my.model.People
這個就是沒有默認的構造方法造成的,所以要在實體類中加入默認的無參構造方法。
4) 重寫equals
和hashCode
方法。equals方法用於判斷兩個對象是否相同,EntityManger通過find方法來查找Entity時,是根據equals的返回值來判斷的。hashCode方法返回當前對象的哈希碼(我驗證EntityManger,不重寫也沒事。);
1.2、編寫實體類:People
package com.my.model; import javax.persistence.*; @Entity @Table(name = "people") //@IdClass(PeopleKey.class) public class People extends PeopleKey{ // 復合主鍵要用這個注解 @EmbeddedId private PeopleKey id; @Column(name = "age") private int age; @Column(name = "address") private String address; // 省略setter,getter方法 @Override public String toString() { return "People [id=" + id + ", age=" + age + ", address=" + address + "]"; } }
1.3 測試:
@Service public class PeopleService { @Resource private PeopleRepository peopleRepository; public People findOne() { PeopleKey peopleKey = new PeopleKey(); peopleKey.setName("張三"); peopleKey.setIdcardno("340123"); People people = peopleRepository.findOne(peopleKey); return people; } }
控制台上的輸出結果:
People [id=PeopleKey [name=張三, idcardno=340123], age=3, address=分解分]
二、采用@IdClass來注解復合主鍵
過程和@Embeddable差不多,這里直接貼例子。
@Entity @Table(name = "people") @IdClass(PeopleKey.class) public class People implements Serializable { // @EmbeddedId // private PeopleKey id; @Id @Column(name = "name") private String name; @Id @Column(name = "idcardno") private String idcardno; @Column(name = "age") private int age; @Column(name = "address") private String address; }
public class PeopleKey implements Serializable { // @Id // @Column(name = "name") private String name; // @Id // @Column(name = "idcardno") private String idcardno; }
采用這個方法的我參考博客里有一篇,寫的比較詳細,但是感覺這個方法不好,本身就已經在PeopleKey中把主鍵給封裝了,但是在實體類People中還要把復合主鍵給加入進去,不夠簡介,采用第一種方法,就很簡單,而且也體現了Java類封裝的思想。
三、EntityManager的驗證,直接上代碼
package com.my.model; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Embeddable; import javax.persistence.Entity; import javax.persistence.Id; //@Embeddable public class PeopleKey implements Serializable { // @Id // @Column(name = "name") private String name; // @Id // @Column(name = "idcardno") private String idcardno; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getIdcardno() { return idcardno; } public void setIdcardno(String idcardno) { this.idcardno = idcardno; } @Override public String toString() { return "PeopleKey [name=" + name + ", idcardno=" + idcardno + "]"; } }
package com.my.model; import java.io.Serializable; import javax.persistence.*; @Entity @Table(name = "people") @IdClass(PeopleKey.class) public class People { // @EmbeddedId // private PeopleKey id; @Column(name = "age") private int age; @Column(name = "address") private String address; // public PeopleKey getId() { // return id; // } // // public void setId(PeopleKey id) { // this.id = id; // } // @Id @Column(name = "name") private String name; @Id @Column(name = "idcardno") private String idcardno; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getIdcardno() { return idcardno; } public void setIdcardno(String idcardno) { this.idcardno = idcardno; } public int getAge() { return age; } public People() { super(); } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "People [age=" + age + ", address=" + address + ", name=" + name + ", idcardno=" + idcardno + "]"; } }
測試:
@RequestMapping(value = "/useEntityManager") public void findUseEntityManager() throws Exception { PeopleKey peopleKey = new PeopleKey(); peopleKey.setName("張三"); peopleKey.setIdcardno("340123"); People people = entityManager.find(People.class,peopleKey); System.out.println(people.toString()); }
結果:
People [age=3, address=分解分, name=張三, idcardno=340123]
參考博客:
1、https://www.cnblogs.com/linjiqin/archive/2011/03/09/1978680.html