6.3.4.主键类和复合类
有时关系映射要求一个主键由多个持久化属性复合而成,例如,我们的关系模型明确指明实体Customer的唯一标识通过
last name和安全码代替自动生成的数字键.这些被称作复合主键.Java持久化规范提供了多种途径映射这种类型的模型。
其中的一种是通过@javax.persistence.IdClass.注释;其它的是通过@javax.persistence.EmbeddedId注释.
6.3.4.1. @IdClass 注释
第一种方法定义主键类(和复合主键)使用@IdClass注释.组件类不用使用主键在其中.但是不使用它来与实体管理器
交互当查找一个持久化对象通过它的主键.@IdClass是类级的注释并且指定那个键类将被使用当与实体管理器交互时.
@Target(TYPE)
@Retention(RUNTIME)
public @interface IdClass
{
Class value( );
}
在你的组件类中,你指明一个或多个属性做为主键,使用@ID注释.这些属性将映射, 成准确的属性在@IdClass.
让我们看以下将Customer组件类改成复合主键为name和安全码.首先,让我们定义一个主键类:
package com.titan.domain;
public class CustomerPK
implements java.io.Serializable
private String lastName;
private long ssn;
public CustomerPK( ) {}
public CustomerPK(String lastName, long ssn)
{
this.lastName = lastName;
this.ssn = ssn;
}
public String getLastName( ) { return this.lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
public long getSsn( ) { return ssn; }
public void setSsn(long ssn) { this.ssn = ssn; }
public boolean equals(Object obj)
{
if (obj == this) return true;
if (!(obj instanceof CustomerPK)) return false;
CustomerPK pk = (CustomerPK)obj;
if (!lastName.equals(pk.lastName)) return false;
if (ssn != pk.ssn) return false;
return true;
}
public int hashCode( )
{
return lastName.hashCode( ) + ssn.hashcode;
}
}
主键类必需满足下列条件:
※必需被序列化
※必需有一个公共的无参构造方法
※必需实现equals()和hashCode()方法
Customer组件必需有同样要求的属性同CustomerPK类的属性被加上@Id注释的.
package com.titan.domain;
import javax.persistence.*;
@Entity
@IdClass(CustomerPK.class)
public class Customer implements java.io.Serializable {
private String firstName;
private String lastName;
private long ssn;
public String getFirstName( ) { return firstName; }
public void setFirstName(String firstName) { this.firstName = firstName; }
@Id
public String getLastName( ) { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
@Id
public long getSsn( ) { return ssn; }
public void setSsn(long ssn) { this.ssn = ssn; }
}
注意:主键自动生成不支持复合键和主键类.你需要手工创建键值.
让我们看一下等价的XML文件:
<entity-mappings>
<entity class="com.titan.domain.Customer" access="PROPERTY">
<id-class>com.titan.domain.CustomerPK</id-class>
<attributes>
<id name="lastName"/>
<id name="ssn"/>
</attributes>
</entity>
</entity-mappings>
<id-class>元素是<entity>的子元素,并且它的值是完全有资格做主键类的类名,注意,多个<id>元素映射成主键类.
主键类用于当你查询Customer组件时:
CustomerPK pk = new CustomerPK("Burke", 9999999);
Customer cust = entityManager.find(Customer.class, pk);
无论你何时调用EntityManager的方法像find()或getreference(),你必需使用主键类才能识别这个实体.
1. @Override
2. public int
3. final int prime = 31;
4. int result = 1;
5. null) ? 0
6. null) ? 0
7. null) ? 0
8. return
9. }
10.
11. @Override
12. public boolean
13. if (this
14. return true;
15. if (obj == null)
16. return false;
17. if
18. return false;
19. final
20.
21. if (cnincd == null) {
22. if (other.cnincd != null)
23. return false;
24. else if
25. return false;
26.
27. if (nedityp == null) {
28. if (other.nedityp != null)
29. return false;
30. else if
31. return false;
32.
33. if (kaishacd == null) {
34. if (other.kaishacd != null)
35. return false;
36. else if
37. return false;
38. return true;
39. }