时间:2021-05-20
一、一对多单向关联映射
一对多关系的对象模型在日常生活中也经常看到,就拿学生和班级来说,一个班级里有多个学生,所以班级和学生的关系是一对多的关系,映射到对象模型中,如下图:
对象模型说明了这种一对多的关系是由一的一端来维护的,那么映射成关系模型就是一个班级字段下面会有多个学生,这样就形成了一对多的关系,通过班级能够查询获得学生信息,对应的关系模型如下图:
1、基本配置
有了对象模型接下来就让它们映射为对应的关系代码,在进行关系映射时需要在一的一端添加<one-to-many>标签,另外还需要在一的一端添加Set属性,它支持延迟加载,然后在映射文件添加set标签,并指明一对多的关系,这样就能够在一的一端查询获取多的一端。
Classes类及映射文件:
它是模型中最重要的一端,在该端需要添加对应的set属性,并在配置文件中添加set标签,在set标签中配置相应的<one-to-many>对象,具体Classes.java对象代码如下:
Classes对象中使用了set属性,但是只是说明了延迟加载的属性,并没有为属性配置对应的对象,属性的对象是要在映射文件中来配置的,需要添加set标签,并在set标签中添加<one-to-many>标签,具体如下代码:
<?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、基本操作
在对数据库的操作无非是读和写两种,修改也属于写的一种,接下来看看是如何向数据库中写入和读取操作的。
(1)写入数据:
写入数据需要注意的是一对多的关系,所以在添加的时候需要添加多个学生类,另外由于在classes中添加了对应的set属性,所以在添加Student对象时应该使用HashSet来添加,这样既可实现一对多的关系,具体如下代码:
那么运行上面的测试用例生成的对应的数据写入到数据库中后如下图:
(2)读取数据:
写入操作相对简单,只需要把所有加载的对象都添加到Transient状态下,运行相应的方法就可以插入内容,但是对应的读取操作就会稍微复杂点,因为需要迭代获取所有的学生对象,所以这种一对多的关系效率并不很高,具体代码如下:
生成的相应的语句及信息如下语句:
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二、一对多双向关联映射
这里继续采用学生和班级作为示例,班级和学生之间是一对多的关系,一个班级中拥有多名学生,和上篇文章不同的是这里的关系是双向的,也就是一的一端和多的一端同时维护关联关系,所以它的对象图如下:
对应的关系模型图没有太大的变化,因为它们之间的关系是双向的,所以在关系模型中两端同时维护关联关系,映射到关系模型中如下图所示:
在一对多的单向关联中映射文件只需要在一的一端进行特殊配置就可以,使用<one-to-many>配置,并在对象模型中使用set迭代器来设置外联的对象模型,但是不同的是在双向的关联中需要在多的一端添加对应的另一端的外键关联,这时候就必须在多的一端使用<many-to-one>的关联关系来标明这种双向性。
1、映射
这里还使用Classes和Student来做示例,在Classes一端的内容和上文相同不会发生变换,但是多的一端Student的配置会发生变化,也就是在映射文件中需要添加<many-to-one>标签。
Student.hbm.xml映射文件配置需要添加外键列<many-to-one>标签,并且该列的名称要和Classes.hbm.xml的外键列的名称一致,具体如下代码:
Classes.hbm.xml映射文件的配置和上篇文章相同,需要注意的是在Classes.java文件中添加了set属性映射对应了Student对象,所以在映射文件中需要添加set标签来指示为对象模型中使用了set迭代器,具体配置如下代码:
<?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.src.hibernate.Classes" table="t_classes"> <id name="id"> <generator class="native"/> </id> <property name="name"/> <set name="students" inverse="true"> <key column="classesid"></key> <one-to-many class="com.src.hibernate.Student"></one-to-many> </set> </class> </hibernate-mapping>2、类
映射文件的配置是直接对应着类来的,所以有了映射文件就能够写出相应的类,相同的有了类就能够知道对应的映射文件如何编写,那来看看相应的类代码如何编写。
Student.java类,需要在类中添加关联的班级对象属性,在加载Student时能获得Classes的相关信息。
Classes.java文件具体代码内容见上篇文章,这里就不在详述。
有了对象模型接下来生成关系模型,生成的SQL语句如下:
3、数据操作
建立表结构后来编写测试方法来验证数据的操作,首先来看看数据的插入,向表结构中插入数据,写入数据时会有两种情况,一种是首先创建一个Classes对象,并将对象写入到数据库中,然后创建Student对象,在Classes对象中添加学生对象;另外一种是先创建学生对象,并将学生对象写入数据库中,然后创建Classes对象将学生对象加入到Classes对象中,这两种类型的操作最后是不相同的,来对比下。
3.1 先写班级后写学生
先把班级写入到数据库中后,Classes对象进入了Transient状态,并在数据库中有了一行,这时再写Student对象,Student对象会查找对应的Classes的主键将其写入到表中,所以此时关系模型中的数据都是非空的,保存的代码如下:
对应的写入数据库中的信息列表如下图:
3.2 先写学生后写班级
先把学生写入到数据库中此时因为学生表需要获取对应的班级列的主键信息,但是因为班级信息转化到Transient状态,所以在写入学生信息时会有null值,代码如下:
写入后对应的数据库视图如下:
对比两种写入操作,因为两个写入的先后顺序不同所以出现了不同的结果,但因为是双向的关联关系所以在写入时并不会发生异常。
4、读取操作
相对于写入数据而言,读取数据就变得很简单了,因为是双向的关联所以数据的读取也是双向的,可以从任何一端读取另一端的信息,如下代码:
public void testLoad1(){ Session session=null; try{ session=HibernateUtils.getSession(); session.beginTransaction(); //通过班级读取学生信息 Classes classes=(Classes)session.load(Classes.class,1); 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()); } //通过学生信息读取班级信息 Student stu=new Student(); stu=(Student)session.load(Student.class, 1); System.out.println("通过学生加载班级信息Classes.id= "+stu.getClasses().getId()); 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=class Hibernate: select students0_.classesid as classesid1_, students0_.id as id1_, students0_.id as id0_0_, students0_.name as name0_0_, students0_.classesid as classesid0_0_ from t_student students0_ where students0_.classesid=? student.name=lisi student.name=zhangsan通过学生加载班级信息Classes.id= 1
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
JSP开发之hibernate之单向多对一关联的实例一对多的基础上来测试单向多对一的关联hibernate多对一的关联关系定义:和单向一对多不同的是:一对多是在
一、双向主键关联双向的主键关联其实是单向一对一主键关联的一种特殊情况,只不过要在关联对象的两端的映射文件中都要进行的配置,另外还要在主映射的主键一端采用fore
Hibernate多对多关联映射(many-to-many)在操作和性能方面都不太理想,所以多对多的映射使用较少,实际使用中最好转换成一对多的对象模型;Hibe
一对多关联映射映射原理一对多关联映射和多对一关联映射的映射原理是一致的,都是在多的一端加入一个外键,指向一的一端。关联关系都是由多端维护,只是在写映射时发生了变
作为一个ORM框架,hibernate肯定也需要满足我们实现表与表之间进行关联的需要。hibernate在关联方法的实现很简单。下面我们先来看看一对一的做法:不