JPA 联结主键的配置
JPA 联合主键的配置
两个或多个字段组成的主键,我们叫联合主键。在面向对象中,我们用JPA怎么定义这种情况呢?
怎么定义联合主键?用面向对象的思想来思考的话,联合主键里的复合主键(字段),可以把它看成一个整体,然后采用一个主键类来描述这个复合主键的字段。
关于联合主键类,大家一定要遵守以下几点JPA规范:
- 必须提供一个public的无参数构造函数。
- 必须实现序列化接口。
- 必须重写hashCode()和equals()这两个方法。这两个方法应该采用复合主键的字段作为判断这个对象是否相等的。
- 联合主键类的类名结尾一般要加上PK两个字母代表一个主键类,不是要求而是一种命名风格。
ArtLinePK.java
- package cn.itcast.bean;
- import java.io.Serializable;
- import javax.persistence.Column;
- import javax.persistence.Embeddable;
- @Embeddable
- //这个注解代表ArtLinePK这个类是用在实体里面,告诉JPA的实现产品:在实体类里面只是使用这个类定义的属性。
- //简单的理解为:ArtLinePK里的属性可以看成是ArtLine类里的属性,好比ArtLinePK的属性就是在ArtLine里定义的。
- public class ArtLinePK implements Serializable{
- private String startCity;
- private String endCity;
- public ArtLinePK() {
- }
- public ArtLinePK(String startCity, String endCity) {
- this.startCity = startCity;
- this.endCity = endCity;
- }
- @Column(length=3)
- public String getStartCity() {
- return startCity;
- }
- public void setStartCity(String startCity) {
- this.startCity = startCity;
- }
- @Column(length=3)
- public String getEndCity() {
- return endCity;
- }
- public void setEndCity(String endCity) {
- this.endCity = endCity;
- }
- @Override
- public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((endCity == null) ? 0 : endCity.hashCode());
- result = prime * result
- + ((startCity == null) ? 0 : startCity.hashCode());
- return result;
- }
- @Override
- public boolean equals(Object obj) {
- if (this == obj)
- return true;
- if (obj == null)
- return false;
- if (getClass() != obj.getClass())
- return false;
- final ArtLinePK other = (ArtLinePK) obj;
- if (endCity == null) {
- if (other.endCity != null)
- return false;
- } else if (!endCity.equals(other.endCity))
- return false;
- if (startCity == null) {
- if (other.startCity != null)
- return false;
- } else if (!startCity.equals(other.startCity))
- return false;
- return true;
- }
- }
这个联合主键类,应该作为实体类的一个主键(实体标识符,id)。
ArtLine.java
- package cn.itcast.bean;
- import javax.persistence.Column;
- import javax.persistence.EmbeddedId;
- import javax.persistence.Entity;
- @Entity
- public class ArtLine {
- private ArtLinePK id; //用面向对象的思想去思考的话,这个复合主键看成一个整体,由复合主键类ArtLinePK来描述。
- private String name;
- public ArtLine() {
- }
- public ArtLine(ArtLinePK id) {
- this.id = id;
- }
- public ArtLine(String startCity, String endCity, String name) {
- this.id = new ArtLinePK(startCity, endCity);
- this.name = name;
- }
- @EmbeddedId //按照JPA规范要求,我们并不是用@Id来标注它。
- //@EmbeddedId 这个注解用于标注id这个属性为实体的标识符,因为我们使用的是复合主键类,所以我们要用@EmbeddedId这个专门针对复合主键类的标志实体标识符的注解。
- public ArtLinePK getId() {
- return id;
- }
- public void setId(ArtLinePK id) {
- this.id = id;
- }
- @Column(length=20)
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
我们的复合主键类,目前为止,已经定义好了。定义好了之后,接着我们就看它生成的数据库表是否满足复合主键这么一种情况。
ArtLineTest.java
- package junit.test;
- import javax.persistence.EntityManager;
- import javax.persistence.EntityManagerFactory;
- import javax.persistence.Persistence;
- import org.junit.BeforeClass;
- import org.junit.Test;
- import cn.itcast.bean.ArtLine;
- public class ArtLineTest {
- @BeforeClass
- public static void setUpBeforeClass() throws Exception {
- }
- @Test public void save(){
- EntityManagerFactory factory = Persistence
- .createEntityManagerFactory("itcast");
- EntityManager em = factory.createEntityManager();
- em.getTransaction().begin();
- em.persist(new ArtLine("PEK","SHA","北京到上海"));
- em.getTransaction().commit();
- em.close();
- factory.close();
- }
- }
- 测试成功后,可以去查询看一下对应表的结构. 想想其中的原理.