Hibernate关系映射之many-to-many(多对多)
在表设计中,我们一般都会考虑表与表之间的关系,现在我来介绍一下表与表之间的几种对应关系
many-to-many 多对多 比如一个用户可以有多种角色 一种角色可以对用多个不同的用户
所以角色和用户之间的关系是多对多的关系 一般要用第三张表表示两者对应的关系
one-to-many 一对多 比如一个老师可以对应很多个学生
many-to-one 相反的是多对一
one-to-one 一对一 比如公民和身份证就是一一对应的
Demo实验:学生与课程之间的关系
1.创建StuCourse类和StuCourse.hbm.xml 表示Student与Course之间的对应关系
1 package com.ansibee.domain; 2 3 public class StuCourse { 4 private Integer id; 5 private Student student; 6 private Course course; 7 private Integer grade; 8 public Integer getId() { 9 return id; 10 } 11 public void setId(Integer id) { 12 this.id = id; 13 } 14 public Student getStudent() { 15 return student; 16 } 17 public void setStudent(Student student) { 18 this.student = student; 19 } 20 public Course getCourse() { 21 return course; 22 } 23 public void setCourse(Course course) { 24 this.course = course; 25 } 26 public Integer getGrade() { 27 return grade; 28 } 29 public void setGrade(Integer grade) { 30 this.grade = grade; 31 } 32 }
<!--StuCourse.hbm.xml-->
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <hibernate-mapping package="com.ansibee.domain"> 5 <class name="StuCourse" > 6 <id name="id" type="java.lang.Integer"> 7 <generator class="increment"> 8 <param name="increment">stucourse_inc</param> 9 </generator> 10 </id> 11 <property name="grade" type="java.lang.Integer"> 12 <column name="grade" length="3"/> 13 </property> 14 <many-to-one name="course" column="course_id"/> 15 <many-to-one name="student" column="student_id"/> 16 </class> 17 </hibernate-mapping>
2.创建Student类和Student.hbm.xml文件
1 package com.ansibee.domain; 2 3 import java.util.Set; 4 5 public class Student { 6 private Integer id; 7 private String name; 8 private Set<StuCourse> stuCourses; 9 public Integer getId() { 10 return id; 11 } 12 public void setId(Integer id) { 13 this.id = id; 14 } 15 public String getName() { 16 return name; 17 } 18 public void setName(String name) { 19 this.name = name; 20 } 21 public Set<StuCourse> getStuCourses() { 22 return stuCourses; 23 } 24 public void setStuCourses(Set<StuCourse> stuCourses) { 25 this.stuCourses = stuCourses; 26 } 27 }
<!--Student.hbm.xml-->
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <hibernate-mapping package="com.ansibee.domain"> 5 <class name="Student"> 6 <id name="id" type="java.lang.Integer"> 7 <generator class="increment"> 8 <param name="increment">stu_inc</param> 9 </generator> 10 </id> 11 <property name="name" type="java.lang.String"> 12 <column name="name" length="64"/> 13 </property> 14 <!-- 这里我们配置了one-to-many 一个学生可以对应多个选课记录 --> 15 <set name="stuCourses"> 16 <key column="student_id"/> 17 <one-to-many class="StuCourse"/> 18 </set> 19 </class> 20 </hibernate-mapping>
3.创建Course类和Course.hbm.xml文件
1 package com.ansibee.domain; 2 3 import java.util.Set; 4 5 public class Course { 6 private Integer id; 7 private String name; 8 private Set<StuCourse> stuCourses; 9 public Integer getId() { 10 return id; 11 } 12 public void setId(Integer id) { 13 this.id = id; 14 } 15 public String getName() { 16 return name; 17 } 18 public void setName(String name) { 19 this.name = name; 20 } 21 public Set<StuCourse> getStuCourses() { 22 return stuCourses; 23 } 24 public void setStuCourses(Set<StuCourse> stuCourses) { 25 this.stuCourses = stuCourses; 26 } 27 }
<!--Course.hbm.xml-->
1 <?xml version="1.0" encoding="utf-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 4 <hibernate-mapping package="com.ansibee.domain"> 5 <class name="Course"> 6 <id name="id" type="java.lang.Integer"> 7 <generator class="increment"> 8 <param name="increment">course_inc</param> 9 </generator> 10 </id> 11 <property name="name" type="java.lang.String"> 12 <column name="name" length="64"/> 13 </property> 14 <!-- 配置one-to-many 表示一门课程可以对应多个选课记录 --> 15 <set name="stuCourses"> 16 <key column="course_id"/> 17 <one-to-many class="StuCourse"/> 18 </set> 19 </class> 20 </hibernate-mapping>
4.完成以上步骤就可以创建Hibernate工具类完成CRUD操作
1 package com.ansibee.util; 2 import java.util.List; 3 4 import org.hibernate.Query; 5 import org.hibernate.Session; 6 import org.hibernate.SessionFactory; 7 import org.hibernate.Transaction; 8 import org.hibernate.cfg.Configuration; 9 10 final public class HibernateUtil { 11 private static SessionFactory sessionFactory=null; 12 //使用线程局部模式 13 private static ThreadLocal<Session> threadLocal=new ThreadLocal<Session>(); 14 private HibernateUtil(){}; 15 static { 16 sessionFactory=new Configuration().configure().buildSessionFactory(); 17 } 18 19 //关闭sessionFactory 20 public static void closeSessionFactory(){ 21 sessionFactory.close(); 22 } 23 24 //获取全新的全新的session 25 public static Session openSession(){ 26 return sessionFactory.openSession(); 27 } 28 //获取和线程关联的session 29 public static Session getCurrentSession(){ 30 31 Session session=threadLocal.get(); 32 //判断是否得到 33 if(session==null){ 34 session=sessionFactory.openSession(); 35 //把session对象设置到 threadLocal,相当于该session已经和线程绑定 36 threadLocal.set(session); 37 } 38 return session; 39 40 } 41 42 //提供一个统一的查询方法 hql形式 from类 where 条件=?.. 43 public static List executeQuery(String hql,String[] parameters){ 44 45 Session session = null; 46 List list = null; 47 48 try { 49 session = openSession(); 50 Query query = session.createQuery(hql); 51 //先判断是否有参数绑定 52 if(parameters!=null&¶meters.length>0){ 53 for(int i=0;i<parameters.length;i++){ 54 query.setString(i, parameters[i]); 55 } 56 } 57 list = query.list(); 58 } catch (Exception e) { 59 e.printStackTrace(); 60 throw new RuntimeException(e.getMessage()); 61 }finally{ 62 if(session!=null&&session.isOpen()){ 63 session.close(); 64 } 65 } 66 return list; 67 } 68 69 //提供一个统一的查询方法(带分页)hql形式 from 类 where 条件=?.. 70 public static List executeQueryByPage(String hql,String[] parameters,int pageSize,int pageNow){ 71 72 Session session = null; 73 List list = null; 74 75 try { 76 session = openSession(); 77 Query query = session.createQuery(hql); 78 //先判断是否有参数绑定 79 if(parameters!=null&¶meters.length>0){ 80 for(int i=0;i<parameters.length;i++){ 81 query.setString(i, parameters[i]); 82 } 83 } 84 85 //分页 86 query.setFirstResult((pageNow-1)*pageSize).setMaxResults(pageSize); 87 88 list = query.list(); 89 } catch (Exception e) { 90 e.printStackTrace(); 91 throw new RuntimeException(e.getMessage()); 92 }finally{ 93 if(session!=null&&session.isOpen()){ 94 session.close(); 95 } 96 } 97 return list; 98 } 99 100 //统一的添加方法 101 public static void save(Object obj){ 102 Session session=null; 103 Transaction ts=null; 104 105 try { 106 session=openSession(); 107 ts=session.beginTransaction(); 108 session.save(obj); 109 ts.commit(); 110 } catch (Exception e) { 111 if(ts!=null){ 112 ts.rollback(); 113 } 114 throw new RuntimeException(e.getMessage()); 115 }finally{ 116 if(session!=null&&session.isOpen()){ 117 session.close(); 118 } 119 } 120 } 121 122 //统一提供一个修改和删除(批量hql)hql"delete update ...??" 123 public static void executeUpdate(String hql,String[] parameters){ 124 125 Session session=null; 126 Transaction ts =null; 127 try { 128 session=openSession(); 129 ts=session.beginTransaction(); 130 Query query=session.createQuery(hql); 131 //先判断是否有参数要绑定 132 if(parameters!=null&¶meters.length>0){ 133 for(int i=0;i<parameters.length;i++){ 134 query.setString(i, parameters[i]); 135 } 136 } 137 query.executeUpdate(); 138 ts.commit(); 139 } catch (Exception e) { 140 e.printStackTrace(); 141 throw new RuntimeException(e.getMessage()); 142 }finally{ 143 if(session!=null&&session.isOpen()){ 144 session.close(); 145 } 146 } 147 } 148 }
5.配置hibernate.cfg.xml
1 <?xml version='1.0' encoding='UTF-8'?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 5 <!-- Generated by MyEclipse Hibernate Tools. --> 6 <hibernate-configuration> 7 8 <session-factory> 9 <property name="myeclipse.connection.profile">com.mysql.jdbc.Driver</property> 10 <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 11 <property name="connection.password">123</property> 12 <property name="connection.username">root</property> 13 <property name="connection.url">jdbc:mysql://localhost:3306/employee</property> 14 <property name="connection.driver_class">com.mysql.jdbc.Driver</property> 15 <property name="show_sql">true</property> 16 <!-- 配置让hibernate自动创建关系模型(表) --> 17 <property name="format_sql">false</property> 18 <property name="hbm2ddl.auto">update</property> 19 <mapping resource="com/ansibee/domain/Course.hbm.xml" /> 20 <mapping resource="com/ansibee/domain/StuCourse.hbm.xml" /> 21 <mapping resource="com/ansibee/domain/Student.hbm.xml" /> 22 </session-factory> 23 24 </hibernate-configuration>
6.编写测试类TestMain
1 package com.ansibee.view; 2 3 import org.hibernate.Session; 4 import org.hibernate.Transaction; 5 6 import com.ansibee.domain.Course; 7 import com.ansibee.domain.StuCourse; 8 import com.ansibee.domain.Student; 9 import com.ansibee.util.HibernateUtil; 10 11 public class TestMain { 12 13 public static void main(String[] args) { 14 15 Session session = null; 16 Transaction ts = null; 17 18 try { 19 // 使用基础模板 20 session = HibernateUtil.getCurrentSession(); 21 ts = session.beginTransaction(); 22 23 //添加一个学生,一门课程,选课 24 Student stu1 = new Student(); 25 stu1.setName("小共"); 26 27 Course course = new Course(); 28 course.setName("C#"); 29 30 StuCourse sc = new StuCourse(); 31 sc.setGrade(95); 32 sc.setCourse(course); 33 sc.setStudent(stu1); 34 35 //顺序保存 36 session.save(stu1); 37 session.save(course); 38 session.save(sc); 39 40 ts.commit(); 41 } catch (Exception e) { 42 if (ts != null) { 43 ts.rollback(); 44 } 45 e.printStackTrace(); 46 47 // TODO: handle exception 48 } finally { 49 if (session != null && session.isOpen()) { 50 session.close(); 51 } 52 } 53 } 54 55 }
7.测试运行