EJB3.0中关于Jpa的复合主键
当我们需要使用一个或多个属性变量(表中的一列或多列)联合起来作为主键,我们需要使用复合主键。在EJB3.0中复合主键要求我们编写一个复合主键类( Composite Primary Key Class )。下面是个小例子,在Student中要用sid和name做复合主键。
Student实体类:
1 import javax.persistence.Column;
2 import javax.persistence.Entity;
3 import javax.persistence.Id;
4 import javax.persistence.IdClass;
5
6 @Entity
7 @IdClass(StudentPK.class)
8 public class Student {
9
10 private String sid;
11 private String name;
12 private String age;
13
14 @Id
15 public String getSid() {
16 return sid;
17 }
18 public void setSid(String sid) {
19 this.sid = sid;
20 }
21
22 @Id
23 public String getName() {
24 return name;
25 }
26 public void setName(String name) {
27 this.name = name;
28 }
29
30 @Column
31 public String getAge() {
32 return age;
33 }
34 public void setAge(String age) {
35 this.age = age;
36 }
37
38 }
2 import javax.persistence.Entity;
3 import javax.persistence.Id;
4 import javax.persistence.IdClass;
5
6 @Entity
7 @IdClass(StudentPK.class)
8 public class Student {
9
10 private String sid;
11 private String name;
12 private String age;
13
14 @Id
15 public String getSid() {
16 return sid;
17 }
18 public void setSid(String sid) {
19 this.sid = sid;
20 }
21
22 @Id
23 public String getName() {
24 return name;
25 }
26 public void setName(String name) {
27 this.name = name;
28 }
29
30 @Column
31 public String getAge() {
32 return age;
33 }
34 public void setAge(String age) {
35 this.age = age;
36 }
37
38 }
主键StudentPK类:
1 import java.io.Serializable;
2
3 public class StudentPK implements Serializable{
4
5 private static final long serialVersionUID = 1L;
6
7 private String sid;
8 private String name;
9
10 public StudentPK(){}
11 public StudentPK(String sid,String name){
12 this.sid = sid;
13 this.name = name;
14 }
15
16 public String getSid() {
17 return sid;
18 }
19 public void setSid(String sid) {
20 this.sid = sid;
21 }
22 public String getName() {
23 return name;
24 }
25 public void setName(String name) {
26 this.name = name;
27 }
28
29 @Override
30 public int hashCode() {
31 final int prime = 31;
32 int result = 1;
33 result = prime * result + ((name == null) ? 0 : name.hashCode());
34 result = prime * result + ((sid == null) ? 0 : sid.hashCode());
35 return result;
36 }
37
38 @Override
39 public boolean equals(Object obj) {
40 if (this == obj)
41 return true;
42 if (obj == null)
43 return false;
44 if (getClass() != obj.getClass())
45 return false;
46 final StudentPK other = (StudentPK) obj;
47 if (name == null) {
48 if (other.name != null)
49 return false;
50 } else if (!name.equals(other.name))
51 return false;
52 if (sid == null) {
53 if (other.sid != null)
54 return false;
55 } else if (!sid.equals(other.sid))
56 return false;
57 return true;
58 }
59
60 }
2
3 public class StudentPK implements Serializable{
4
5 private static final long serialVersionUID = 1L;
6
7 private String sid;
8 private String name;
9
10 public StudentPK(){}
11 public StudentPK(String sid,String name){
12 this.sid = sid;
13 this.name = name;
14 }
15
16 public String getSid() {
17 return sid;
18 }
19 public void setSid(String sid) {
20 this.sid = sid;
21 }
22 public String getName() {
23 return name;
24 }
25 public void setName(String name) {
26 this.name = name;
27 }
28
29 @Override
30 public int hashCode() {
31 final int prime = 31;
32 int result = 1;
33 result = prime * result + ((name == null) ? 0 : name.hashCode());
34 result = prime * result + ((sid == null) ? 0 : sid.hashCode());
35 return result;
36 }
37
38 @Override
39 public boolean equals(Object obj) {
40 if (this == obj)
41 return true;
42 if (obj == null)
43 return false;
44 if (getClass() != obj.getClass())
45 return false;
46 final StudentPK other = (StudentPK) obj;
47 if (name == null) {
48 if (other.name != null)
49 return false;
50 } else if (!name.equals(other.name))
51 return false;
52 if (sid == null) {
53 if (other.sid != null)
54 return false;
55 } else if (!sid.equals(other.sid))
56 return false;
57 return true;
58 }
59
60 }
主键类必需满足下列条件:
(1)必需被序列化
(2)必需有一个公共的无参构造方法
(3)必需实现equals()和hashCode()方法
当你查询Student实体时必须使用主键类才能识别实体如:
StudentPK pk = new StudentPK("bj1001","jakin");
Student student = entityManager.find(Student.class, pk);
Student student = entityManager.find(Student.class, pk);
在测试本例时笔者犯了两个低级的错误,一是测试环境的数据库不是项目运行的数据库,二是实体类中的属性命名用了关键字,请引以为戒。