一对多
来源:互联网 发布:较量无声 知乎 编辑:程序博客网 时间:2024/04/28 11:26
一、单向一对多
前篇文章中曾经对多对一的关系展开了讨论,其中主要使用的是<many-to-one>的关系,在多的一端维护一的一端,那和今天要讨论的一对多的关系它们之间是否有关联呢?在关系和对象模型中存在了一对多关系所以理所当然就会有多对一的关系,Hibernate同样提供了一对多关系的标签<one-to-many>。
一对多关系的对象模型在日常生活中也经常看到,就拿学生和班级来说,一个班级里有多个学生,所以班级和学生的关系是一对多的关系,映射到对象模型中,如下图:
对象模型说明了这种一对多的关系是由一的一端来维护的,那么映射成关系模型就是一个班级字段下面会有多个学生,这样就形成了一对多的关系,通过班级能够查询获得学生信息,对应的关系模型如下图:
1、基本配置
有了对象模型接下来就让它们映射为对应的关系代码,在进行关系映射时需要在一的一端添加<one-to-many>标签,另外还需要在一的一端添加Set属性,它支持延迟加载,然后在映射文件添加set标签,并指明一对多的关系,这样就能够在一的一端查询获取多的一端。
Classes类及映射文件
它是模型中最重要的一端,在该端需要添加对应的set属性,并在配置文件中添加set标签,在set标签中配置相应的<one-to-many>对象,具体Classes.java对象代码如下:
- <pre name="code" class="java">package com.src.hibernate;
- import java.util.Set;
- public class Classes {
- private int id;
- 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;
- }
- private String name;
- //Set支持延迟加载
- private Set students;
- public Set getStudents() {
- return students;
- }
- public void setStudents(Set students) {
- this.students = students;
- }
- }
- <?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.hibernate.Classes" table="t_classes">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <set name="students">
- <key column="classesid"></key>
- <one-to-many class="com.hibernate.Student"></one-to-many>
- </set>
- </class>
- </hibernate-mapping>
对应的Student对象中的代码和映射文件不需要什么特殊的配置,只需要按照通常的写法编写即可,具体的配置方法不再详述,很简单。配置好后需要生成对应的SQL语句,将对象模型转化为关系模型时Hibernate生成相应的语句如下:
- alter table t_student drop foreign key FK4B9075705E0AFEFE
- drop table if exists t_classes
- drop table if exists t_student
- create table t_classes (id integer not null auto_increment, name varchar(255), primary key (id))
- create table t_student (id integer not null auto_increment, name varchar(255), classesid integer, primary key (id))
- alter table t_student add index FK4B9075705E0AFEFE (classesid), add constraint FK4B9075705E0AFEFE foreign key (classesid) references t_classes (id)
生成的对应的关系模型如下图:
对比SQL语句和关系模型,相应的表之间的关联是通过外键来维护的,首先是创建两张表,并指定表的主键,最后添加一对多的外键关联关系。
2、基本操作
在对数据库的操作无非是读和写两种,修改也属于写的一种,接下来看看是如何向数据库中写入和读取操作的。
写入数据
写入数据需要注意的是一对多的关系,所以在添加的时候需要添加多个学生类,另外由于在classes中添加了对应的set属性,所以在添加Student对象时应该使用HashSet来添加,这样既可实现一对多的关系,具体如下代码:
- public void testSave2(){
- Session session=null;
- try{
- session=HibernateUtils.getSession();
- session.beginTransaction();
- Student student1=new Student();
- student1.setName("zhangsan");
- session.save(student1);
- Student student2=new Student();
- student2.setName("lisi");
- session.save(student2);
- Classes classes=new Classes();
- classes.setName("ClassOne");
- 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);
- }
- }
那么运行上面的测试用例生成的对应的数据写入到数据库中后如下图:
读取数据
写入操作相对简单,只需要把所有加载的对象都添加到Transient状态下,运行相应的方法就可以插入内容,但是对应的读取操作就会稍微复杂点,因为需要迭代获取所有的学生对象,所以这种一对多的关系效率并不很高,具体代码如下:
- package com.test.hibernate;
- import java.util.Iterator;
- import java.util.Set;
- import com.src.hibernate.*;
- import junit.framework.TestCase;
- import org.hibernate.Session;
- public class One2ManyTest extends TestCase {
- public void testLoad1(){
- Session session=null;
- try{
- session=HibernateUtils.getSession();
- session.beginTransaction();
- //获取主键为5的班级信息
- Classes classes=(Classes)session.load(Classes.class,5);
- //打印班级信息
- System.out.println("classes.name="+classes.getName());
- //设置学生集合,通过班级加载学生集合
- Set students=classes.getStudents();
- //迭代集合,打印集合中学生的信息
- for(Iterator iter=students.iterator();iter.hasNext();){
- Student student=(Student)iter.next();
- System.out.println("student.name="+student.getName());
- }
- session.getTransaction().commit();
- }catch(Exception e){
- e.printStackTrace();
- session.getTransaction().rollback();
- }finally{
- HibernateUtils.closeSession(session);
- }
- }
- }
生成的相应的语句及信息如下语句:
- Hibernate: select classes0_.id as id1_0_, classes0_.name as name1_0_ from t_classes classes0_ where classes0_.id=?
- classes.name=ClassOne
- Hibernate: select students0_.classesid as classesid1_, students0_.id as id1_, students0_.id as id0_0_, students0_.name as name0_0_ from t_student students0_ where students0_.classesid=?
- student.name=lisi
- student.name=zhangsan
结语
一对多的关系也是经常用到的,但是这种关系在加载时效率会不高,因为需要维护的数据较多,所以不建议使用一对多的关系,可以考虑多对一的关系,这样在加载时其实是一种一对一的关系,加载的效率较高,关系和对象模型得到了优化。这里只是讨论了单向的一对多,下篇文章讨论双向的关联关系。
0 0
- 一对多:
- 一对多
- 一对多
- 一对多
- 一对多
- 单向一对多和双向一对多
- Hibernate 一对多例
- hibernate一对多例子
- hibernate 一对多映射
- hibernate一对多
- hibernate一对多 更新
- ibatis一对多
- ibatis一对多
- 一对多改成一对一
- Hibernate一对多映射
- JAVA 一对多关系
- Hibernate 一对多
- OneToMany(一对多)
- Red John Game 规律思路题
- OC 数据类型
- Socket.IO 和 Node.js 入门
- UVALive 6428 A+B 扩展欧几里德
- android自定义钟表
- 一对多
- 流程图制作要领
- Socket.io在线聊天室
- 常用Android开发库的说明文档
- 复合主键
- 监听servlet三大作用域创建销毁时间
- 如何选书--转载
- UVALive 6432 Influence 搜索 剪枝
- node.js的npm安装的根目录已经下载的包的根目录查找和设置