两个或多个字段组成的主键,我们叫联合主键。在面向对象中,我们用JPA怎么定义这种情况呢?
怎么定义联合主键?用面向对象的思想来思考的话,联合主键里的复合主键(字段),可以把它看成一个整体,然后采用一个主键类来描述这个复合主键的字段。
关于联合主键类,大家一定要遵守以下几点JPA规范:
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(); } }
字段生成了,看图: