`

JPA多对多

阅读更多

维护端注解

@ManyToMany (cascade = CascadeType.REFRESH)

@JoinTable (//关联表

                   name =  "student_teacher" , //关联表名

                   inverseJoinColumns =  @JoinColumn (name =  "teacher_id" ),//被维护端外键

                   joinColumns =  @JoinColumn (name =  "student_id" ))//维护端外键

被维护端注解

@ManyToMany(

                   cascade = CascadeType.REFRESH,

                   mappedBy = "teachers",//通过维护端的属性关联

                   fetch = FetchType.LAZY)

关系维护端删除时,如果中间表存在些纪录的关联信息,则会删除该关联信息;

关系被维护端删除时,如果中间表存在些纪录的关联信息,则会删除失败 .

 

 

以学生和老师的对应关系为例。一个学生可以拥有多个老师,一个老师也可以拥有多个学生。

学生实体类

package com.taoistwar.jpa.entity.manytomany;

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.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;

@Entity
public class Student {
	private Integer id;
	private String name;
	private Set<Teacher> teachers = new HashSet<Teacher>();

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	@Column(nullable = false, length = 16)
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@ManyToMany(cascade = CascadeType.REFRESH)
	@JoinTable(name = "student_teacher", inverseJoinColumns = @JoinColumn(name = "teacher_id"), joinColumns = @JoinColumn(name = "student_id"))
	public Set<Teacher> getTeachers() {
		return teachers;
	}

	public void setTeachers(Set<Teacher> teachers) {
		this.teachers = teachers;
	}

	public void addTeacher(Teacher teacher) {
		this.teachers.add(teacher);
	}

	public void removeTeachers(Teacher teacher) {
		this.teachers.remove(teacher);
	}

}

 重点在于:

@ManyToMany(cascade = CascadeType.REFRESH)
	@JoinTable(name = "student_teacher", inverseJoinColumns = @JoinColumn(name = "teacher_id"), joinColumns = @JoinColumn(name = "student_id"))
	public Set<Teacher> getTeachers() {
		return teachers;
	}

 老师实体类

package com.taoistwar.jpa.entity.manytomany;

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.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

@Entity
public class Teacher {
	private Integer id;
	private String name;
	private Set<Student> students = new HashSet<Student>();

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	@Column(nullable = false, length = 16)
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@ManyToMany(cascade = CascadeType.REFRESH, mappedBy = "teachers", fetch = FetchType.LAZY)
	public Set<Student> getStudents() {
		return students;
	}

	public void setStudents(Set<Student> students) {
		this.students = students;
	}

      @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;
		Teacher other = (Teacher) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}
}

 重点在于:

@ManyToMany(cascade = CascadeType.REFRESH, mappedBy = "teachers", fetch = FetchType.LAZY)
	public Set<Student> getStudents() {
		return students;
	}

 拥有mappedBy注解的实体类为关系被维护端,另外的实体类为关系维护端的。顾名思意,关系的维护端对关系(在多对多为中间关联表)的CRUD做操作。关系的被维护端没有该操作,不能维护关系。

测试类

package com.taoistwar.jpa.entity.manytomany;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

import org.junit.Test;

public class ManyToMany {
	@Test
	public void save() {
		EntityManagerFactory emf = Persistence
				.createEntityManagerFactory("JPAPU");
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		Student student = new Student();
		student.setName("小李");
		Teacher teacher = new Teacher();
		teacher.setName("大李");
		em.persist(student);
		em.persist(teacher);
		em.getTransaction().commit();
		emf.close();
	}
	
	@Test
	public void bind() {
		EntityManagerFactory emf = Persistence
				.createEntityManagerFactory("JPAPU");
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		Student student = em.find(Student.class, 1);
		Teacher teacher = em.find(Teacher.class, 1);
		student.addTeacher(teacher);
		em.persist(student);
		em.getTransaction().commit();
		emf.close();
	}
	
	@Test
	public void unbind() {
		EntityManagerFactory emf = Persistence
				.createEntityManagerFactory("JPAPU");
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		Student student = em.find(Student.class, 1);
		Teacher teacher = em.find(Teacher.class, 1);
		student.removeTeachers(teacher);
		em.persist(student);
		em.getTransaction().commit();
		emf.close();
	}
	
	@Test
	public void removeTeacher() {
		EntityManagerFactory emf = Persistence
				.createEntityManagerFactory("JPAPU");
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		// 关系被维护端删除时,如果中间表存在些纪录的关联信息,则会删除失败
		em.remove(em.getReference(Teacher.class, 1));
		em.getTransaction().commit();
		emf.close();
	}
	
	@Test
	public void removeStudent() {
		EntityManagerFactory emf = Persistence
				.createEntityManagerFactory("JPAPU");
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		// 关系维护端删除时,如果中间表存在些纪录的关联信息,则会删除该关联信息
		em.remove(em.getReference(Student.class, 1));
		em.getTransaction().commit();
		emf.close();
	}
	
}

 

 

 

 

 

 

 

 

  • JPA.zip (5.7 MB)
  • 下载次数: 182
分享到:
评论
1 楼 nforce_com 2011-05-12  
写的很好,学习了!不过Student 一般情况下不会删除所有的Teacher ,仅会删除某个Teacher ,这里面没太讲清楚,下面加上部分代码:
.........举例,因环境不同略去.......

public void doDeleteDetail(ActionEvent event) {

.........举例,因环境不同略去.......
Set<Teacher > set = getInstance().getTeacher();
Iterator<Teacher > itr = set.iterator();
while (itr.hasNext()) {
Teacher m = itr.next();
if (item.getId().equals(m.getId())) {
log.info("---RequestMap:#0", m.getId());
set.remove(m);
// 实体的改变同步到数据库
getEntityManager().merge(getInstance());
// 会话没有结束,手动flush
getEntityManager().flush();
return;
}
}
}

相关推荐

Global site tag (gtag.js) - Google Analytics