Hibernate表关系映射之多对多映射
来源:互联网 发布:淘宝运营网站 编辑:程序博客网 时间:2024/06/06 04:59
一、多对多的实现原理
在数据库中实现多对多的关系,必须使用连接表。也就是用一个独立的表来存入两个表的主键字段,通过遍历这张表来获取两表的关联关系。
而在我们的对象中,多对多是通过两者对象类中互相建立对方类的对象集合,类似上一篇讲到的一对多的集合类!在Hibernate中是通过<many to many>来进行设置。同样多对多也存在双向和单向之分,表现到Hibernate中就是配置文件和POJO代码的不同。这里以单向映射为例,双向映射与之类似。
二、实例演示
1、建立数据模型
我们以学生与老师关系为例。一个学生可以有多个老师,而一个老师也一样可以有多名学生!这里我们让老师Teacher持有学生Student的集合引用。
Teacher.java
package com.chen.many2many;import java.util.HashSet;import java.util.Set;public class Teacher {private Integer teacherID;private String teacherName;//持有一个student的Set集合private Set<Student> studentSet=new HashSet<>();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;}public Set<Student> getStudentSet() {return studentSet;}public void setStudentSet(Set<Student> studentSet) {this.studentSet = studentSet;}}
Student.java
package com.chen.many2many;import java.util.HashSet;import java.util.Set;public class Student {private Integer studentID;private String studentName;//持有一个teacher的Set集合//private Set<Teacher> teacherSet=new HashSet<>();public Integer getStudentID() {return studentID;}public void setStudentID(Integer studentID) {this.studentID = studentID;}public String getStudentName() {return studentName;}public void setStudentName(String studentName) {this.studentName = studentName;}/*public Set<Teacher> getTeacherSet() {return teacherSet;}public void setTeacherSet(Set<Teacher> teacherSet) {this.teacherSet = teacherSet;}*/}
2、Hibernate配置文件
Student.hbm.xml
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><!-- Generated 2017-3-10 14:43:39 by Hibernate Tools 3.4.0.CR1 --><hibernate-mapping> <class name="com.chen.many2many.Student" table="STUDENTS"> <id name="studentID" type="java.lang.Integer"> <column name="STUDENT_ID" /> <generator class="native" /> </id> <property name="studentName" type="java.lang.String"> <column name="STUDENT_NAME" /> </property> <!-- 指定双向映射时需要加入如下设置 <set name="teacherSet" table="TEACHERS_STUDENTS" inverse="true"> <key> <column name="S_ID" /> </key> <many-to-many class="com.chen.many2many.Teacher" column="T_ID"/> </set> --> </class></hibernate-mapping>
Teacher.hbm.xml
<?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><!-- Generated 2017-3-10 14:43:39 by Hibernate Tools 3.4.0.CR1 --><hibernate-mapping> <class name="com.chen.many2many.Teacher" table="TEACHERS"> <id name="teacherID" type="java.lang.Integer"> <column name="TEACHER_ID" /> <generator class="native" /> </id> <property name="teacherName" type="java.lang.String"> <column name="TEACHER_NAME" /> </property> <!-- name是该类(Teacher)中持有的另一端的集合属性名 ,table指定了中间表的名字--> <set name="studentSet" table="TEACHERS_STUDENTS"> <key> <!-- 当前类(Teacher)映射到中间表上时,使用的外键名称 --> <column name="T_ID" /> </key> <!-- many-to-many完成多对多映射,class指定另一端(Student)的类名。 column指定另一端(Student)在中间表中对应的外键名 --> <many-to-many class="com.chen.many2many.Student" column="S_ID" /> </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> <!-- Hibernate 连接数据库的基本信息 --> <property name="connection.username">root</property> <property name="connection.password">root</property> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://192.168.1.148:3306/hibernate5</property><!-- Hibernate 的基本配置 --><!-- Hibernate 使用的数据库方言,为了使mysql自动生成数据表对于mysql5.x使用如下设置 --><property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property><!-- 运行时是否打印 SQL --> <property name="show_sql">true</property> <!-- 运行时是否格式化 SQL --> <property name="format_sql">true</property> <!-- 生成数据表的策略 --> <property name="hbm2ddl.auto">update</property> <!-- 设置 Hibernate 的事务隔离级别 --> <property name="connection.isolation">2</property> <!-- 删除对象后, 使其 OID 置为 null --> <property name="use_identifier_rollback">true</property> <!-- 配置 C3P0 数据源 --> <property name="hibernate.c3p0.max_size">10</property> <property name="hibernate.c3p0.min_size">5</property> <property name="c3p0.acquire_increment">2</property> <property name="c3p0.idle_test_period">2000</property> <property name="c3p0.timeout">2000</property> <property name="c3p0.max_statements">10</property> <!-- 设定 JDBC 的 Statement 读取数据的时候每次从数据库中取出的记录条数 --> <property name="hibernate.jdbc.fetch_size">100</property> <!-- 设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小 --> <property name="jdbc.batch_size">30</property> <!-- 需要关联的 hibernate 映射文件 .hbm.xml --> <mapping resource="com/chen/many2many/Student.hbm.xml"/><mapping resource="com/chen/many2many/Teacher.hbm.xml"/> </session-factory></hibernate-configuration>
3、编写测试方法
HibernateTest.java
package com.chen.many2many;import java.util.Iterator;import java.util.Set;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.Transaction;import org.hibernate.cfg.Configuration;import org.hibernate.service.ServiceRegistry;import org.hibernate.service.ServiceRegistryBuilder;public class HibernateTest {private static SessionFactory sessionFactory;private static Session session;private static Transaction transaction;//定义事务初始化函数public static void init(){Configuration configuration = new Configuration().configure();ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry();sessionFactory = configuration.buildSessionFactory(serviceRegistry);session = sessionFactory.openSession();transaction = session.beginTransaction();}//定义事务结束时的处理函数public static void doit(){transaction.commit();session.close();sessionFactory.close();}//编写自己的处理过程public static void testSave(){//学生: a,b,c//教师:A,B//所属关系A(a,b) B(a,b,c)//初始化学生Student a=new Student();a.setStudentName("a");Student b = new Student();b.setStudentName("b");Student c=new Student();c.setStudentName("c");//初始化老师Teacher A=new Teacher();A.setTeacherName("A");Teacher B=new Teacher();B.setTeacherName("B");//设置关联关系A.getStudentSet().add(a);A.getStudentSet().add(b);B.getStudentSet().add(a);B.getStudentSet().add(b);B.getStudentSet().add(c);//保存session.save(a);session.save(b);session.save(c);session.save(A);session.save(B);}public static void testGet(){Teacher teacherResult=(Teacher) session.get(Teacher.class, 1);System.out.println(teacherResult.getTeacherName());Set<Student> set=teacherResult.getStudentSet();for (Iterator iterator = set.iterator(); iterator.hasNext();) {Student student = (Student) iterator.next();System.out.println(student.getStudentName());}}public static void main(String[] args) {HibernateTest.init();HibernateTest.testSave();HibernateTest.testGet();HibernateTest.doit();System.out.println("完成---------");}}
4、运行结果
数据表students
数据表teachers
中间表teachers_students
控制台显示结果:
三、多对多双向映射注意项
1、双向 n-n 关联需要两端都持有对方的一个集合对象引用。
2、双向n-n关联必须使用连接表。
3、集合属性应增加 key 子元素用以映射外键列, 集合元素里还应增加many-to-many子元素关联实体类。
4、在双向 n-n 关联的两边,都需指定连接表的表名及外键列的列名.。两个集合元素 set 的 table 元素的值必须指定,而且必须相同,这样就指定了同一张连接表。
5、set元素的两个子元素:key 和 many-to-many 都必须指定 column 属性,其中,key 和 many-to-many 分别指定本持久化类和关联类在连接表中的外键列名,因此两边的 key 与 many-to-many 的column属性交叉相同。也就是说,一边的set元素的key的 cloumn值为a,many-to-many 的 column 为b;则另一边的 set 元素的 key 的 column 值 b,many-to-many的 column 值为 a。
6、对于双向 n-n 关联, 必须把其中一端的 inverse 设置为 true, 否则两端都维护关联关系可能会造成主键冲突。
- Hibernate表关系映射之多对多映射
- Hibernate关系映射之多对多关系
- Hibernate映射关系之多对多关系映射
- hibernate关系映射之多对多
- hibernate映射关系之多对多
- 【Hibernate五】关系映射之多对多
- Hibernate关联关系映射之多对多关联关系
- Hibernate之多对多关系之间的关系映射
- Hibernate多表映射之多对一
- Hibernate之多对多映射
- Hibernate关系配置之多对多映射配置
- Hibernate关系映射之多对多映射的两种方式
- 技术分析之Hibernate的关联关系映射之多对多映射
- Hibernate关联映射之多对多
- Hibernate初探之多对多映射
- Hibernate学习之多对多映射
- Hibernate表关系映射之一对多映射
- Hibernate关联映射之多对多单/双向关联映射
- Java动态代理的两种实现方法
- Spring监听器
- 基于WebStorm, React和Ant.Design开发WebAppDemo
- tensorflow训练出的模型识别的demo
- C++第一次实验(基础班)项目2
- Hibernate表关系映射之多对多映射
- MySQL 中 delete ,update语句的子查询限制
- div+css自适应高度
- java调用webservice天气预报(SOAP请求的方式获取天气信息并解析返回的XML)
- 怎么通过公众号来快速学习python编程?
- SylixOS SPI Flash驱动移植
- GYM 100827 I.Salary Inequity(线段树)
- Android LayoutInflater原理分析,带你一步步深入了解View(一)
- apt-get update和apt-get upgrade的区别