一对多关联映射和多对一关联映射的映射原理是一样一样的,所以说嘛,知识都是相通的,一通百通,为什么说一对多关联映射和多对一关联映射是一样的呢?因为她们都是在多的一端加入一个外键,指向一的一段,关联关系都是在多的一端进行维护,只是我们在写映射的时候发生了变化。
一对多和多对一的映射原理是一样的,但是她们之间也存在着小小的区别,毕竟世界上没有两片完全相同的叶子,她们之间的区别就是维护的关系不同,我们先来看多对一,多端维护一端的关系,在加载多端的时候,可以将一端加载上来;一对多,一端维护多端的关系,在加载一端的时候,可以将多端加载上来。一对多关联映射也存在两种策略,单向和双向,今天这篇博文,小编就来简单的介绍一下一对多关联映射,希望对有需要的小伙伴有帮助,不足之处,还请小伙伴们多多指教`(*∩_∩*)′。
一对多单向关联映射
我们都知道,一个班级是由多个学生组成的,ok,今天的故事就从班级和学生开始拉开帷幕,我们依然从uml入手,首先我们来看对象模型,如下图所示:
从对象模型中,我们可以看出,Classes持有Student的一个引用,由于是单向关联,所以数据在加载Classes的时候,会把Student加载上来,但是Student并不知道Classes的存在。接着,我们开始来编写代码的部分。
第一步、编写实体Classes && Student,代码如下所示,首先我们来编写Classes,代码如下所示:
package com.bjpowernode.hibernate;
import java.util.Set;
public class Classes {
private int id;
private String name;
private Set Students;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getStudents() {
return Students;
}
public void setStudents(Set students) {
Students = students;
}
Student的代码如下所示:
package com.bjpowernode.hibernate;
public class Student {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
第二步、编写映射文件,首先编写Classes.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">
<hibernate-mapping>
<class name="com.bjpowernode.hibernate.Classes" table="t_classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name = "students">
<key column="classesid"/>
<one-to-many class="com.bjpowernode.hibernate.Student"/>
</set>
</class>
</hibernate-mapping>
接着编写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">
<hibernate-mapping>
<class name ="com.bjpowernode.hibernate.Student" table="t_student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
第三步、编写hibernate.cfg.xml的代码,建立数据库并且添加相应的映射,代码如下所示:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory >
<!-- MySql数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 数据库名称 -->
<property name="hibernate.connection.url"> jdbc:mysql:///hibernate_one2many_1</property>
<!-- 数据库的用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库的密码 -->
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 显示语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 格式排版 -->
<!-- <property name="hibernate.format_sql">true</property> -->
<mapping resource="com/bjpowernode/hibernate/Student.hbm.xml"/>
<mapping resource="com/bjpowernode/hibernate/Classes.hbm.xml"/>
</session-factory>
</hibernate-configuration>
接着创建数据库,并且运行ExportDB,生成相应的表结构如下所示:
接着,我们向表里面插入数据,代码如下所示:
package com.bjpowernode.hibernate;
import java.util.HashSet;
import java.util.Set;
import junit.framework.TestCase;
import org.hibernate.Session;
public void testSave2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student1 = new Student();
student1.setName("张三");
session.save(student1);
Student student2 = new Student();
student2.setName("李四");
session.save(student2);
Classes classes = new Classes();
classes.setName("动力节点");
Set students = new HashSet();
students.add(student1);
students.add(student2);
classes.setStudents(students);
//可以成功保存数据
//但是会发出多余的update语句来维持关系
session.save(classes);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
运行代码效果如下所示:
从上面的demo实例我们可以看出来,因为多端Student不知道Classes的存在,也就是Student不维护与Classes的关系,所以在保存Student的时候,字段classesid为空,如果该字段设置为非空,则将无法保存数据;因为Student不维护关系,而Classes维护关系,Classes将会发出多余的update语句。介绍完了一对多单向关联映射,接着我们来一起学习一下一对多双向关联映射,对象模型如下所示:
双向关联映射
双向关联映射对比单向关联映射,对象的加载方向由单向变成了双向。我们依然以为Classes和Student为例进行讲解。
第一步、编写实体Classes && Student,代码如下所示,首先我们来编写Classes,代码如下所示:
package com.bjpowernode.hibernate;
import java.util.Set;
public class Classes {
private int id;
private String name;
private Set Students;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set getStudents() {
return Students;
}
public void setStudents(Set students) {
Students = students;
}
}
接着,编写Student的代码,如下所示:
package com.bjpowernode.hibernate;
public class Student {
private int id;
private String name;
private Classes classes;
public Classes getClasses() {
return classes;
}
public void setClasses(Classes classes) {
this.classes = classes;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
第二步、编写映射文件,首先编写Classes.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">
<hibernate-mapping>
<class name="com.bjpowernode.hibernate.Classes" table="t_classes">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name = "students">
<key column="classesid"/>
<one-to-many class="com.bjpowernode.hibernate.Student"/>
</set>
</class>
接着编写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">
<hibernate-mapping>
<class name ="com.bjpowernode.hibernate.Student" table="t_student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="classes" column="classesid"/>
</class>
</hibernate-mapping>
第三步、编写hibernate.cfg.xml的代码,建立数据库并且添加相应的映射,代码如下所示:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory >
<!-- MySql数据库驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 数据库名称 -->
<property name="hibernate.connection.url"> jdbc:mysql:///hibernate_one2many_2</property>
<!-- 数据库的用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- 数据库的密码 -->
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- 显示语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 格式排版 -->
<!-- <property name="hibernate.format_sql">true</property> -->
<mapping resource="com/bjpowernode/hibernate/Student.hbm.xml"/>
<mapping resource="com/bjpowernode/hibernate/Classes.hbm.xml"/>
</session-factory>
</hibernate-configuration>
接着创建数据库,并且运行ExportDB,生成相应的表结构如下所示:
接着,我们向表里面插入数据,代码如下所示:
package com.bjpowernode.hibernate;
import java.util.HashSet;
import java.util.Set;
import junit.framework.TestCase;
import org.hibernate.Session;
public void testSave2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student1 = new Student();
student1.setName("张三");
session.save(student1);
Student student2 = new Student();
student2.setName("李四");
session.save(student2);
Classes classes = new Classes();
classes.setName("动力节点");
Set students = new HashSet();
students.add(student1);
students.add(student2);
classes.setStudents(students);
//可以成功保存数据
//但是会发出多余的update语句来维持关系
session.save(classes);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
运行代码,效果如下所示:
小编寄语:为什么多对一关联映射不存在单向一对多中的问题呢?在多对一关联映射里面,由于关系是在多的一端进行维护的,加载的时候从多的一端进行加载,当然没有问题。总结一下:在多对一关联映射中,如果用到,经常采用双向的方式来完成映射,弥补单向加载时的问题。ok,今天的hibernate一对多映射就介绍到这里,还请小伙伴们多多指教,在下一篇博文中,小编将继续介绍hibernate映射的相关知识,敬请期待……