多对多映射

学生和老师就是多对多的关系。一个学生有多个老师,一个老师教多个学生。多对多映射采取中间表连接的映射策略,建立的中间表将分别引入两边的主键作为外键。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());
}
%>