多对多映射
学生和老师就是多对多的关系。一个学生有多个老师,一个老师教多个学生。多对多映射采取中间表连接的映射策略,建立的中间表将分别引入两边的主键作为外键。EJB3 对于中间表的元数据提供了可配置的方式,用户可以自定义中间表的表名,列名。
需要映射的数据表:
Student.java
package com.foshanshop.ejb3.bean; import java.io.Serializable; import java.util.HashSet; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToMany; import javax.persistence.Table; @SuppressWarnings("serial") @Entity @Table(name = "Student") public class Student implements Serializable{ private Integer studentid; private String StudentName; private Set<Teacher> teachers = new HashSet<Teacher>(); public Student() {} public Student(String studentName) { StudentName = studentName; } @Id @GeneratedValue public Integer getStudentid() { return studentid; } public void setStudentid(Integer studentid) { this.studentid = studentid; } @Column(nullable=false, length=32) public String getStudentName() { return StudentName; } public void setStudentName(String studentName) { StudentName = studentName; } @ManyToMany(mappedBy = "students") public Set<Teacher> getTeachers() { return teachers; } public void setTeachers(Set<Teacher> teachers) { this.teachers = teachers; } }
@ManyToMany 注释表示Student 是多对多关系的一边,mappedBy 属性定义了Student 为双向关系的维护端(owning side)。
Teacher.java
package com.foshanshop.ejb3.bean; import java.io.Serializable; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.Table; @SuppressWarnings("serial") @Entity @Table(name = "Teacher") public class Teacher implements Serializable{ private Integer teacherid; private String TeacherName; private Set<Student> students = new HashSet<Student>(); public Teacher() {} public Teacher(String teacherName) { TeacherName = teacherName; } @Id @GeneratedValue public Integer getTeacherid() { return teacherid; } public void setTeacherid(Integer teacherid) { this.teacherid = teacherid; } @Column(nullable=false, length=32) public String getTeacherName() { return TeacherName; } public void setTeacherName(String teacherName) { TeacherName = teacherName; } @ManyToMany(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY) @JoinTable(name = "Teacher_Student", joinColumns = {@JoinColumn(name = "Teacher_ID", referencedColumnName = "teacherid")}, inverseJoinColumns = {@JoinColumn(name = "Student_ID", referencedColumnName = "studentid")}) public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } public void addStudent(Student student) { if (!this.students.contains(student)) { this.students.add(student); } } public void removeStudent(Student student) { this.students.remove(student); } }
@ManyToMany 注释表示Teacher 是多对多关系的一端。@JoinTable 描述了多对多关系的数据表关系。name 属性指定中间表名称,joinColumns 定义中间表与Teacher 表的外键关系。上面的代码中,中间表Teacher_Student的Teacher_ID 列是Teacher 表的主键列对应的外键列,inverseJoinColumns 属性定义了中间表与另外一端(Student)
的外键关系。
TeacherDAOBean.java
package com.foshanshop.ejb3.impl; import javax.ejb.Remote; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import com.foshanshop.ejb3.TeacherDAO; import com.foshanshop.ejb3.bean.Student; import com.foshanshop.ejb3.bean.Teacher; @Stateless @Remote ({TeacherDAO.class}) public class TeacherDAOBean implements TeacherDAO { @PersistenceContext protected EntityManager em; public void insertTeacher(String name, String[] studentnames) { Teacher teacher = new Teacher(name); if (studentnames!=null){ for(int i=0;i<studentnames.length; i++){ teacher.addStudent(new Student(studentnames[i])); } } em.persist(teacher); } public Teacher getTeacherByID(Integer teacherid) { Teacher teacher= em.find(Teacher.class, teacherid); if (teacher!=null) teacher.getStudents().size(); return teacher; } public Student getStudentByID(Integer studentid) { Student student= em.find(Student.class, studentid); if (student!=null) student.getTeachers().size(); return student; } }
ManyToManyTest.jsp
import="com.foshanshop.ejb3.TeacherDAO, com.foshanshop.ejb3.bean.*, javax.naming.*, java.util.*"%> <% Properties props = new Properties(); props.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory"); props.setProperty("java.naming.provider.url", "localhost:1099"); props.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming"); InitialContext ctx = new InitialContext(props); try { TeacherDAO teacherdao = (TeacherDAO) ctx.lookup("TeacherDAOBean/remote"); teacherdao.insertTeacher("李老师",new String[]{"张小红","朱小光","龚利"}); Teacher teacher = teacherdao.getTeacherByID(new Integer(1)); if (teacher!=null){ out.println("======= 获取编号为1的老师姓名:"+ teacher.getTeacherName() +" ======<br>"); Iterator iterator = teacher.getStudents().iterator(); while (iterator.hasNext()){ Student student = (Student) iterator.next(); out.println(" 他的学生:"+ student.getStudentName() +"<br>"); } }else{ out.println("没有找到编号为1的老师<br>"); } Student student = teacherdao.getStudentByID(new Integer(1)); if (student!=null){ out.println("======= 获取编号为1的学生姓名:"+ student.getStudentName() +" ======<br>"); Iterator iterator = student.getTeachers().iterator(); while (iterator.hasNext()){ Teacher tc = (Teacher) iterator.next(); out.println(" 他的老师:"+ tc.getTeacherName() +"<br>"); } }else{ out.println("没有找到编号为1的学生<br>"); } } catch (Exception e) { out.println(e.getMessage()); } %>