清单 8.News 实体类使用定义好的主键类
@Entity
public class News implements Serializable {
private static final long serialVersionUID = 1L;
@EmbeddedId
private NewsId id;
private String content;
// Getters and Setters
}清单 9 是持久化后生成的数据库表的结构,可以看出来这个表如我们预想的一样是 Title 和 Language 的联合 主键。
清单 9. 使用主键类生成的表结构
CREATE TABLE `news` (
`CONTENT` varchar(255) default NULL,
`TITLE` varchar(255) NOT NULL,
`LANGUAGE` varchar(255) NOT NULL,
PRIMARY KEY (`TITLE`,`LANGUAGE`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
IdClass 复合主键
IdClass 这种复合主键策略,在主键类上 和 Embeddable 这种复合主键策略稍有不同。如清单 10,这个策略中的主键类不需要使用任何注解 (annotation),但是仍 然必须重写 hashCode() 和 equals() 两个方法。其实也就是将 Embeddable 这种复合主键策略中的主键类的 @Embeddable 注解去掉就可以了。
清单 10. IdClass 复合主键策略中的主键类
public class NewsId implements
Serializable {
private static final long serialVersionUID = 1L;
private String title;
private String language;
public String getLanguage() {
return language;
}
public void setLanguage(String language) {
this.language = language;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final NewsId other = (NewsId) obj;
if ((this.title == null) ? (other.title != null) : !this.title.equals(other.title)) {
return false;
}
if ((this.language == null) ? (other.language != null) : !this.language.equals(
other.language)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 5;
hash = 41 * hash + (this.title != null ? this.title.hashCode() : 0);
hash = 41 * hash + (this.language != null ? this.language.hashCode() : 0);
return hash;
}
}从清单 11 中可以看出这个 News 实体类首先使用 @IdClass (NewsId.class) 注解指定了主键类。同时在类中 也复写了主键类中的两个字段,并分别用 @Id 进行了注解。
清单 11. IdClass 策略中使用复合主键的 News 类
@Entity
@IdClass(NewsId.class)
public class News implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private String title;
@Id
private String language;
private String content;
// Getters and Setters
}