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?}主键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?}主键类必需满足下列条件:
(1)必需被序列化
(2)必需有一个公共的无参构造方法
(3)必需实现equals()和hashCode()方法
当你查询Student实体时必须使用主键类才能识别实体如:
??? StudentPK?pk?=?new?StudentPK("bj1001","jakin");
????Student?student?=?entityManager.find(Student.class,?pk);在测试本例时笔者犯了两个低级的错误,一是测试环境的数据库不是项目运行的数据库,二是实体类中的属性命名用了关键字,请引以为戒。