JPA中的多对多和联合主键映射

下面的Java Project,示例的是多对多映射

首先是学生的实体Bean

package com.jadyer.model; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; /** * 学生的实体Bean * @see 三个属性的setter和getter略 */ @Entity public class Student { @Id @GeneratedValue private Integer id; @Column(length=10, nullable=false) private String name; //@JoinTable(name="student_teacher") //这种情况下中间表的字段名默认为students_id和teachers_id //@JoinTable注解的inverseJoinColumns属性指的是被维护端的外键,joinColumns用来定义关联表中维护端的外键 @ManyToMany(cascade=CascadeType.REFRESH) @JoinTable(name="student_teacher", joinColumns=@JoinColumn(name="student_id"), inverseJoinColumns=@JoinColumn(name="teacher_id")) private Set<Teacher> teachers = new HashSet<Teacher>(); public Student(){} public Student(String name) { this.name = name; } /** * 建立学生跟老师的关系 */ public void addTeacher(Teacher teacher){ this.teachers.add(teacher); } /** * 解除学生跟老师的关系 */ public void removeTeacher(Teacher teacher){ if(this.teachers.contains(teacher)){ this.teachers.remove(teacher); } } }

然后是教师的实体Bean

package com.jadyer.model; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; /** * 教师的实体Bean * @see 三个属性的setter和getter略 */ @Entity public class Teacher { @Id @GeneratedValue private Integer id; @Column(length=10, nullable=false) private String name; //双向多对多是一种对等关系,所以我们可以人为的决定关系维护端 @ManyToMany(mappedBy="teachers", cascade=CascadeType.REFRESH) private Set<Student> students = new HashSet<Student>(); public Teacher(){} public Teacher(String name) { this.name = name; } //用来判断两个对象是否相同,所以要重写hashCode()和equals()方法 @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.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 Teacher other = (Teacher) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; return true; } }

用到的位于src下的META-INF目录下的persistence.xml文件

<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"> <persistence-unit name="JPAManyToManyDemo" transaction-type="RESOURCE_LOCAL"> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect" /> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true"/> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver" /> <property name="hibernate.connection.username" value="scott" /> <property name="hibernate.connection.password" value="jadyer" /> <property name="hibernate.connection.url" value="jdbc:oracle:thin:@127.0.0.1:1521:jadyer" /> </properties> </persistence-unit> </persistence>

最后是使用的JUnit4单元测试类ManyToManyTest.java

package com.jadyer.junit; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import org.junit.Test; import com.jadyer.model.Student; import com.jadyer.model.Teacher; public class ManyToManyTest { /** * 添加学生和老师 */ @Test public void save(){ EntityManagerFactory factory = Persistence.createEntityManagerFactory("JPAManyToManyDemo"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); em.persist(new Student("令狐冲")); em.persist(new Teacher("风清扬")); em.getTransaction().commit(); em.close(); factory.close(); } /** * 建立学生跟老师的关系 */ @Test public void buildTS(){ EntityManagerFactory factory = Persistence.createEntityManagerFactory("JPAManyToManyDemo"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Student student = em.find(Student.class, 3); student.addTeacher(em.getReference(Teacher.class, 4)); em.getTransaction().commit(); em.close(); factory.close(); } /** * 解除学生跟老师的关系 */ @Test public void removeTS(){ EntityManagerFactory factory = Persistence.createEntityManagerFactory("JPAManyToManyDemo"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Student student = em.find(Student.class, 3); student.removeTeacher(em.getReference(Teacher.class, 4)); em.getTransaction().commit(); em.close(); factory.close(); } /** * 删除老师 */ @Test public void deleteTeacher(){ EntityManagerFactory factory = Persistence.createEntityManagerFactory("JPAManyToManyDemo"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Student student = em.find(Student.class, 1); Teacher teacher = em.getReference(Teacher.class, 2); student.removeTeacher(teacher); //Teacher是关系被维护端,所以它没有权利直接更新外键,所以必须在解除关系之后再删除Teacher em.remove(em.getReference(Teacher.class, 2)); em.getTransaction().commit(); em.close(); factory.close(); } /** * 删除学生 */ @Test public void deleteStudent(){ EntityManagerFactory factory = Persistence.createEntityManagerFactory("JPAManyToManyDemo"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Student student = em.getReference(Student.class, 1); //Student是关系维护端,有权利更新外键,所以能够直接删除 em.remove(student); em.getTransaction().commit(); em.close(); factory.close(); } }

上面就是多对多映射的示例代码


下面是联合主键映射的示例代码

下面的Java Project,演示联合主键映射

首先是飞机航线的复合主键类

package com.jadyer.model; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Embeddable; /** * 飞机航线的复合主键类 * @see 通常复合主键类的类名尾部都带有PK字样 * @see 在复合主键类中通常只定义用作主键的字段 * @see 作为复合主键类,以下三点是必须要遵守的JPA规范 * @see 1.必须提供一个public的无参构造函数 * @see 2.必须实现序列化接口 * @see 3.必须重写hashCode()和equals()方法,其中以复合主键类的字段作为判断依据 * @see ------------------------------------------------------------------------ * @see 两个数据的setter和getter略 */ @SuppressWarnings("serial") @Embeddable //即嵌入注解,它是用来告诉JPA,我们只是使用复合主键类里面的属性,作为实体的持久化字段 public class AirLinePK implements Serializable { //飞机航线在国际上是有标准的,通常都会采用三字码来代表出发城市和目的城市 //所谓三字码就是三个英文字母。比如北京的三字码是PEK,广州是CAN,上海是SHA //所以这里字段的长度只需要设成3位就可以 @Column(length=3) private String startCity; @Column(length=3) private String endCity; public AirLinePK(){} public AirLinePK(String startCity, String endCity) { this.startCity = startCity; 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 AirLinePK other = (AirLinePK) 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; } }

然后是飞机航线的实体Bean

package com.jadyer.model; import javax.persistence.Column; import javax.persistence.EmbeddedId; import javax.persistence.Entity; /** * 飞机航线的实体Bean * @see 两个属性的setter和getter略 */ @Entity public class AirLine { @EmbeddedId //用于标注该属性为实体的标识符,该注解专门用于复合主键类 private AirLinePK id; @Column(length=20) private String name; public AirLine(){} public AirLine(String startCity, String endCity, String name){ this.id = new AirLinePK(startCity, endCity); this.name = name; } }

这里用到的persistence.xml与上面多对多映射中用到的,相同,故略去

最后是用到的JUnit4单元测试类CompositePKTest.java

package com.jadyer.junit; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import org.junit.Test; import com.jadyer.model.AirLine; public class CompositePKTest { @Test public void save(){ EntityManagerFactory factory = Persistence.createEntityManagerFactory("JPACompositePKDemo"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); em.persist(new AirLine("PEK", "SHA", "北京飞往上海")); em.getTransaction().commit(); em.close(); factory.close(); } }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值