Hibernate -- 映射多对多双向关联关系
1.
示例代码:
Student.java
package cn.itcast.many2many; import java.util.HashSet; import java.util.Set; @SuppressWarnings("serial") public class Student implements java.io.Serializable { private Integer id; private String name; private Set<Course> courses=new HashSet(0); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Course> getCourses() { return courses; } public void setCourses(Set<Course> courses) { this.courses = courses; } }
Course.java
package cn.itcast.many2many; import java.util.HashSet; import java.util.Set; @SuppressWarnings("serial") public class Course implements java.io.Serializable{ private Integer id; private String name; private Set<Student> studentes=new HashSet(0); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Student> getStudentes() { return studentes; } public void setStudentes(Set<Student> studentes) { this.studentes = studentes; } }
App.java
package cn.itcast.many2many; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.junit.Test; public class App { private static SessionFactory sf=null; static{ Configuration config=new Configuration(); config.configure("cn/itcast/many2many/hibernate.cfg.xml"); config.addClass(Student.class); config.addClass(Course.class); sf=config.buildSessionFactory(); } /* * 知识点4:测试保存 */ @Test public void saveStudentAndCoure(){ Session session=sf.openSession(); Transaction tx=session.beginTransaction(); Student s1=new Student(); s1.setName("风侠"); Student s2=new Student(); s2.setName("雨侠"); Course c1=new Course(); c1.setName("语文"); Course c2=new Course(); c2.setName("数学"); //建立关联关系 s1.getCourses().add(c1); s1.getCourses().add(c2); s2.getCourses().add(c1); s2.getCourses().add(c2); c1.getStudentes().add(s1); c1.getStudentes().add(s2); c2.getStudentes().add(s1); c2.getStudentes().add(s2); session.save(s1); session.save(s2); session.save(c1); session.save(c2); tx.commit(); session.close(); } //知识点5:解除1号学生和1号课程的关联关系 @Test public void removeMany2Many(){ Session session=sf.openSession(); Transaction tx=session.beginTransaction(); //查询1号学生 Student s1=(Student)session.get(Student.class, 1); //查询1号课程 Course c1=(Course)session.get(Course.class, 1); //解除关联关系 s1.getCourses().remove(c1); c1.getStudentes().remove(s1); tx.commit(); session.close(); } //知识点6:改变1号学生和2号课程的关联关系,改为1号学生和1号课程 @Test public void changeMany2Many(){ Session session=sf.openSession(); Transaction tx=session.beginTransaction(); //查询1号学生 Student s1=(Student)session.get(Student.class, 1); //查询1号课程 Course c1=(Course)session.get(Course.class, 1); //查询2号课程 Course c2=(Course)session.get(Course.class, 2); //解除1号学生和2号课程关联关系 s1.getCourses().remove(c2); c2.getStudentes().remove(s1); //建立1号学生和1号课程的关联关系 s1.getCourses().add(c1); c1.getStudentes().add(s1); tx.commit(); session.close(); } //知识点7:删除2号学生,产生异常 @Test public void removeStudent(){ Session session=sf.openSession(); Transaction tx=session.beginTransaction(); //查询2号学生 Student s2=(Student)session.get(Student.class, 2); session.delete(s2); tx.commit(); session.close(); } /* * 知识点8:删除1号课程.这里能删除,因为课程是主控方法 student.hbm.xml配置inverse="true" * * 能删除1号课程 * * 能删除1号课程对应的中间表信息,但不能是删除学生表的信息 */ @Test public void removeCourse(){ Session session=sf.openSession(); Transaction tx=session.beginTransaction(); //查询1号课程 Course c1=(Course)session.get(Course.class, 1); session.delete(c1); tx.commit(); session.close(); } //知识点9:删除1号课程的同时,要把1号和2号学生删掉? cascade="delete", 中间表用到的学生应先删除 @Test public void removeCourseCase(){ Session session=sf.openSession(); Transaction tx=session.beginTransaction(); //查询1号课程 Course c1=(Course)session.get(Course.class, 1); session.delete(c1); tx.commit(); session.close(); } }
Student.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="cn.itcast.many2many.Student" table="student"> <id name="id" type="integer"> <column name="id"/> <generator class="increment"/> </id> <property name="name" type="string"> <column name="name"/> </property> <!--table为中间表--> <set name="courses" table="student_course" inverse="true"> <!--coursees这个集合中放置的是课程对象 通过中间表的学生id,查询该学生要学习的课程 select cid from student_course where sid=1 --> <key column="sid"/> <!-- class表示coursees集合存放的是什么类型的对象 column="cid":通过课程id获取课程对象 select id,name from course where id=cid; --> <many-to-many class="cn.itcast.many2many.Course" column="cid"/> </set> </class> </hibernate-mapping>
Course.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="cn.itcast.many2many.Course" table="course"> <id name="id" type="integer"> <column name="id"/> <generator class="increment"/> </id> <property name="name" type="string"> <column name="name"/> </property> <!--table为中间表--> <set name="studentes" table="student_course" cascade="delete"> <!--coursees这个集合中放置的是课程对象 通过中间表的学生id,查询该学生要学习的课程 select cid from student_course where sid=1 --> <key column="cid"/> <!-- class表示coursees集合存放的是什么类型的对象 column="cid":通过课程id获取课程对象 select id,name from course where id=cid; --> <many-to-many class="cn.itcast.many2many.Student" column="sid"/> </set> </class> </hibernate-mapping>
hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/test</property> <!-- 配置数据库的方言,让hibernate知道连接的是哪个数据库--> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property> <!-- 配置利用javaBean和映射文件生成数据库中的表 hibernate.hbm2ddl.auto值 * create:执行时,先查找该表是否存在,如存在先删除表,在创建表 * none:不能创建表,只能往表中插入数据,如表不存在抛出异常,默认值 * update:执行时, 情况一: 先查找该表是否存在,如果表存在,直接插入,如果表不存在,先创建表,再插入数据. 情况二: 先查找该表是否存在,如果表存在,但表的结构不一样,要修改表的结构 --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 显示hibernate生成的sql语句 --> <property name="hibernate.show_sql">true</property> <!-- 显示格式化得sql语句 --> <property name="hibernate.format_sql">false</property> </session-factory> </hibernate-configuration>