实体bean(十四)多对多映射
mappedBy:
1.表明是双向关联
2.在一对多中避免产生中间表,在不使用mappedBy的一方,即多方设外键来与一方关联
3.双向关系中的反向端必须使用@OneToOne、@OneToMany、@ManyToMany注解中的mappedBy元素来引用持有端的关联属性。
mappedBy元素标注了关系持有者的关系值域或属性;
------------------------------------------------------------------------------------------------------------------------------
student:
package com.persia.jpa.mtm; 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; @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){ this.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) { this.studentName = studentName; } @ManyToMany(mappedBy="students") public Set<Teacher> getTeachers() { return teachers; } public void setTeachers(Set<Teacher> teachers) { this.teachers = teachers; } }
teacher:
package com.persia.jpa.mtm; import java.io.Serializable; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinTable; import javax.persistence.JoinColumn; import javax.persistence.ManyToMany; import javax.persistence.Table; @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){ this.teacherName=teacherName; } @Id @GeneratedValue(strategy=GenerationType.AUTO) public Integer getTeacherid() { return teacherid; } public void setTeacherid(Integer teacherid) { this.teacherid = teacherid; } public String getTeacherName() { return teacherName; } public void setTeacherName(String teacherName) { this.teacherName = teacherName; } @ManyToMany(cascade=CascadeType.PERSIST,fetch=FetchType.LAZY) @JoinTable(name="teacher_student", //指明本方id关联的列名及引用自哪一列 joinColumns={@JoinColumn(name="Teacher_Id",referencedColumnName="teacherid")}, inverseJoinColumns={@JoinColumn(name="Student_Id",referencedColumnName="studentid")} //指明关联方id所对应的列名及引用自哪一列 ) public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } public void addStudent(Student stu){ if(!this.students.contains(stu)){ this.students.add(stu); } } public void removeStudent(Student stu){ this.students.remove(stu); } }
dao:
package com.persia.jpa.mtm; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.ejb.Remote; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; @Stateless @Remote({TeacherDAO.class}) public class TeacherDAOBean implements TeacherDAO { @PersistenceContext private EntityManager em; public TeacherDAOBean() { // TODO Auto-generated constructor stub } @Override public Student getStudentByID(Integer studentid) { Student s=em.find(Student.class, studentid); if(s!=null) s.getTeachers().size(); return s; } @Override public Teacher getTeacherByID(Integer teacherid) { Teacher t=em.find(Teacher.class, teacherid); if(t!=null) t.getStudents().size(); return t; } @Override public void insertTeacher() { Teacher t1=new Teacher(); t1.setTeacherName("persia"); Teacher t2=new Teacher(); t2.setTeacherName("linda"); Student s1=new Student(); s1.setStudentName("aaa"); Student s2=new Student(); s2.setStudentName("bbb"); Set s=new HashSet(); s.add(s1); s.add(s2); t1.setStudents(s); t2.setStudents(s); em.persist(t1); em.persist(t2); } @Override public void removeStudent(Integer studentid) { Student stu=em.find(Student.class, studentid); Set set=stu.getTeachers(); Iterator it=set.iterator(); while(it.hasNext()){ Teacher t=(Teacher)it.next(); t.removeStudent(stu); } stu.setTeachers(null); em.remove(stu); } @Override public void removeTeacher(Integer teacherid) { Teacher t=em.find(Teacher.class, teacherid); em.remove(t); } }
注解mappedBy的一方为主动方,就像order和orderItem里面的order,它通过mappedBy来允许被动方来访问它。
删除的时候,如果被动方是延迟加载,则可以直接删除被动方;否则必须逐一删除,将自己从主动方中删除。
在一对多中,可以直接删除mappedBy的一方,而在多对多中,删除mappedBy的一方时必须逐一解除跟另一方的关系。
这里student是主动方,所有删除student的时候,要先把它的teacher在关联表先删除掉(但teacher表本身的数据不删)。
如果cascade=CascadeType.ALL的时候,删除student,则连teacher也删除了。
(不知道这里的主动被动称呼是否得当?)
test:
package com.persia.jpa.mtmtest; import java.util.Iterator; import java.util.Properties; import javax.naming.InitialContext; import javax.naming.NamingException; import com.persia.jpa.mtm.Student; import com.persia.jpa.mtm.Teacher; import com.persia.jpa.mtm.TeacherDAO; public class TestMTM { /** * @param args * @throws NamingException */ public static void main(String[] args) throws NamingException { 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 context=new InitialContext(props); try{ TeacherDAO tdao=(TeacherDAO)context.lookup("TeacherDAOBean/remote"); // tdao.insertTeacher(); Teacher t=tdao.getTeacherByID(new Integer(1)); if(t!=null){ System.out.println("=====编号为1的老师姓名:"+t.getTeacherName()); Iterator it=t.getStudents().iterator(); while(it.hasNext()){ Student stu=(Student)it.next(); System.out.println("他的学生:"+stu.getStudentName()); } }else{ System.out.println("找不到编号为1的老师的学生"); } tdao.removeStudent(new Integer(1)); }catch(Exception e){ e.printStackTrace(); } } }
database:
mysql> select * from student; +-----------+-------------+ | studentid | studentName | +-----------+-------------+ | 1 | aaa | | 2 | bbb | +-----------+-------------+ 2 rows in set (0.00 sec) mysql> select * from teacher; +-----------+-------------+ | teacherid | teacherName | +-----------+-------------+ | 1 | persia | | 2 | linda | +-----------+-------------+ 2 rows in set (0.00 sec) mysql> select * from teacher_student; +------------+------------+ | Teacher_Id | Student_Id | +------------+------------+ | 1 | 1 | | 1 | 2 | | 2 | 1 | | 2 | 2 | +------------+------------+ 4 rows in set (0.00 sec)
执行删除student 1 之后:(前后对比)
mysql> select * from teacher_student; +------------+------------+ | Teacher_Id | Student_Id | +------------+------------+ | 1 | 1 | | 1 | 2 | | 2 | 1 | | 2 | 2 | +------------+------------+ 4 rows in set (0.00 sec)
后: mysql> select * from teacher_student; +------------+------------+ | Teacher_Id | Student_Id | +------------+------------+ | 1 | 2 | | 2 | 2 | +------------+------------+ 2 rows in set (0.00 sec)
mysql> select * from student; +-----------+-------------+ | studentid | studentName | +-----------+-------------+ | 2 | bbb | +-----------+-------------+ 1 row in set (0.00 sec) mysql> select * from teacher; +-----------+-------------+ | teacherid | teacherName | +-----------+-------------+ | 1 | persia | | 2 | linda | +-----------+-------------+ 2 rows in set (0.00 sec)
当删除teacher时:
tdao.removeTeacher(new Integer(1));
mysql> select * from teacher; +-----------+-------------+ | teacherid | teacherName | +-----------+-------------+ | 2 | linda | +-----------+-------------+ 1 row in set (0.00 sec) mysql> select * from student; +-----------+-------------+ | studentid | studentName | +-----------+-------------+ | 1 | bbb | | 2 | aaa | +-----------+-------------+ 2 rows in set (0.00 sec) mysql> select * from teacher_student; +------------+------------+ | Teacher_Id | Student_Id | +------------+------------+ | 2 | 1 | | 2 | 2 | +------------+------------+ 2 rows in set (0.00 sec)
浙公网安备 33010602011771号