JPA视频学习(五)双向多对多关联配置
1.配置persistence.xml和log4j
配置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="JPAManyToManyPU" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/> <property name = "hibernate.connection.driver_class" value = "com.mysql.jdbc.Driver"/> <property name = "hibernate.connection.url" value = "jdbc:mysql://localhost:3306/jpa?useUnicode=true&characterEncoding=UTF-8"/> <property name = "hibernate.connection.username" value = "root"/> <property name="hibernate.max_fetch_depth" value="3"/> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence>
配置log4j.properties
# For JBoss: Avoid to setup Log4J outside $JBOSS_HOME/server/default/deploy/log4j.xml!
# For all other servers: Comment out the Log4J listener in web.xml to activate Log4J.
log4j.rootLogger=INFO, stdout, logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=/hello.log
log4j.appender.logfile.MaxFileSize=512KB
# Keep three backup files.
log4j.appender.logfile.MaxBackupIndex=3
# Pattern to output: date priority [category] - message
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
2.配置实体bean
student:
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; @Entity public class Student { private Integer id; private String name; private Set<Teacher> teachers=new HashSet<Teacher>(); public Student(){} public Student(String name){ this.name=name; } @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(length=10,nullable=false) public String getName() { return name; } public void setName(String name) { this.name = name; } //一般在多对多很少用到级联的操作。 /** * inverseJoinColumns关系被维护端的外键在中间表中的定义 * JoinColumns 关系维护端的外键在中间表中的定义 */ @ManyToMany(cascade=CascadeType.REFRESH) @JoinTable(name="student_teacher" ,inverseJoinColumns=@JoinColumn(name="teacherid") ,joinColumns=@JoinColumn(name="studentid")) public Set<Teacher> getTeachers() { return teachers; } public void setTeachers(Set<Teacher> teachers) { this.teachers = teachers; } //关系的维护 public void addTeachers(Teacher teacher){ this.teachers.add(teacher); } public void removeTeachers(Teacher teacher){ if(this.teachers.contains(teacher))//通过Teacher重载的hashCode方法来判断 this.teachers.remove(teacher); } }
teacher:
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.ManyToMany; import com.sun.org.apache.bcel.internal.generic.NEW; @Entity public class Teacher { private Integer id; private String name; private Set<Student> student=new HashSet<Student>(); public Teacher(){} public Teacher(String name) { super(); this.name = name; } @Id @GeneratedValue public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @Column(length=10,nullable=false) public String getName() { return name; } public void setName(String name) { this.name = name; } @ManyToMany(mappedBy="teachers",cascade=CascadeType.REFRESH ,fetch=FetchType.LAZY)//关系被维护端 public Set<Student> getStudent() { return student; } public void setStudent(Set<Student> student) { this.student = student; } @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; } }
3.Junit测试
package junit.test; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import org.junit.BeforeClass; import org.junit.Test; import com.persia.bean.Student; import com.persia.bean.Teacher; import com.sun.org.apache.bcel.internal.generic.NEW; public class ManyToManyTest { @BeforeClass public static void setUpBeforeClass() throws Exception { } //@Test public void save(){ EntityManagerFactory factory=Persistence.createEntityManagerFactory("JPAManyToManyPU"); EntityManager eManager=factory.createEntityManager(); eManager.getTransaction().begin(); eManager.persist(new Student("学生1")); eManager.persist(new Teacher("老师1")); eManager.getTransaction().commit(); eManager.close(); factory.close(); } /** * 建立老师与学生的关系 */ //@Test public void buildRelation(){ EntityManagerFactory factory=Persistence.createEntityManagerFactory("JPAManyToManyPU"); EntityManager eManager=factory.createEntityManager(); eManager.getTransaction().begin(); Student student=eManager.find(Student.class, 2); student.addTeachers(eManager.getReference(Teacher.class, 2)); //eManager.merge(arg0)直接更新即可:在托管中,且em是打开的。 eManager.getTransaction().commit(); eManager.close(); factory.close(); } /** * 解除关系 */ //@Test public void relieveRelation(){ EntityManagerFactory factory=Persistence.createEntityManagerFactory("JPAManyToManyPU"); EntityManager eManager=factory.createEntityManager(); eManager.getTransaction().begin(); Student student=eManager.find(Student.class, 1); student.removeTeachers(eManager.getReference(Teacher.class, 1)); //当前处于托管状态,而且em是打开着的,所以直接删除即可。 eManager.getTransaction().commit(); eManager.close(); factory.close(); } /** * 删除老师 */ //@Test public void deleteTeacher(){ EntityManagerFactory factory=Persistence.createEntityManagerFactory("JPAManyToManyPU"); EntityManager eManager=factory.createEntityManager(); eManager.getTransaction().begin(); Student student=eManager.find(Student.class, 1); Teacher teacher=eManager.getReference(Teacher.class, 1); student.removeTeachers(teacher); //先解除关系,再删除 eManager.remove(eManager.find(Teacher.class, 1)); //关系被维护端没有权力更新外键,此时此操作无法执行,有外键约束。 eManager.getTransaction().commit(); eManager.close(); factory.close(); } /** * 删除关系维护端 */ //@Test public void deleteStudent(){ EntityManagerFactory factory=Persistence.createEntityManagerFactory("JPAManyToManyPU"); EntityManager eManager=factory.createEntityManager(); eManager.getTransaction().begin(); eManager.remove(eManager.find(Student.class, 2)); //关系维护端有权力更新外键。 eManager.getTransaction().commit(); eManager.close(); factory.close(); } }