hibernate一对多关联映射——单向(继。空间不够了)(
2012-08-08 16:34
357 查看
十一、接着看存储与加载
建立单元测试类One2ManyTest
package com.bjsxt.hibernate;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import junit.framework.TestCase;
public class One2ManyTest extends TestCase {
}
十二、测试save(保存)
一对多的存储方式应该与多对一不一样。一对多存储的应该是classes。因为班级与学生的关系是在classes类里面的students集合。所以应该是先有学生,把学生建立好之后,再放到Classes类的students这个集合里面。
1、testSave()方法内容如下:
public void testSave(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
Student student1=new Student();
student1.setName("菜10");
Student student2=new Student();
student2.setName("容祖儿");
Set<Student> students=new HashSet<Student>();
students.add(student1);
students.add(student2);
Classes classes=new Classes();
classes.setName("尚学堂");
classes.setStudents(students);
session.save(classes);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
当testSave()方法执行时,会出现这个org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.bjsxt.hibernate.Student 异常。
2、正确的保存testSave2()
public void testSave2(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
//先建立学生对象集合
Student student1=new Student();
student1.setName("菜10");
session.save(student1);
Student student2=new Student();
student2.setName("容祖儿");
session.save(student2);
//用泛型了
//因为班级里的学生是一个集合,所以要构造一个集合出来
Set<Student> students=new HashSet<Student>();
//向集合里面加数据
students.add(student1);
students.add(student2);
//要知道哪个学生所在的班级,要new 班级出来
Classes classes=new Classes();
classes.setName("尚学堂");
//这个班级里面有哪些学生,要用set方法加上去。
//这样这个尚学堂班级里面就有两个学生了
classes.setStudents(students);
session.save(classes);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
2.1执行后出现SQL语句:
insert into t_student (name) values (?)
只保存了学生的name,此时classesid字段值为null.
insert into t_student (name) values (?)
insert into t_classes (name) values (?)
hibernate又连接发了两条update,因为只有两个学生
update就是要把学生的classesid字段值更新上
根据学生id把classesid更新上。
也就是说,要由班级(一的一端)来维护这种关系:你菜10是我们班的,你容祖儿是我们班的。
在一的一端维护这种关系,会发现很多udpate。因为班级不知道会有多少学生。
就是说,由班级(一的端)主动记住这种关系
就如记人的名字一样,就如让姚明来记我们十三亿的人,这个关系要由姚来维护,
他要主动来记,把十三亿人的名字全部记下来。这肯定比较困难。因为由他一个人来更新,来记。
实际上,这种关系在多的一端来维护很容易,就如让我们记住姚明的名字很容易一样的。这是在一的端维护关系的一个缺点。另一个缺点是后面说的,如果在Student.hbm.xml映射文件中,将classesid字段设置为非空的话,则保存时会出错。
update t_student set classid=? where id=?
update t_student set classid=? where id=?
2.2执行结果数据库显示:
mysql> select * from t_classes;
+----+--------+
| id | name |
+----+--------+
| 1 | 尚学堂 |
+----+--------+
1 row in set (0.00 sec)
mysql> select * from t_student;
+----+--------+--------
| id | name |classesid
+----+--------+-------
| 1 | 菜10 | 1
+----+--------+-------
| 2 | 容祖儿 | 1
+----+--------+-------
1 row in set (0.00 sec)
2.3 我们现在分析一下数据库的结构,如这个测试方法,我们是先保存学生对象集合的。可是这时,这个学生对象里面只有名字与id,却没有classesid .可是表字段里是有classesid字段的。是在映射的时候加进去的。
可是如我们的测试方法,还是可以正确执行,班级里面可以加进去两个学生。 这是为什么呢?
原因是,我们的classesid字段是可以为空的。
也就是说,我们先把学生保存进去,可是这时 classesid 字段是没有值的。等到保存Classes时,再更新这个字段,将班级id值更新(update)上去。
如果我们在此Students.hbm.xml文件加上这样一条,让 classesid字段不能为空,再执行这个方法时,在存储时就会失败了,因为clssesid字段在保存时必须要值,不然就存不进去了。
<set name=”students”>
<key column=”classesid” not-null=”true”/>
<ont-to-many class=”com.bjsxt.hibernate.Student”/>
</set>
注:当修改完Students.hbm.xml文件时,要重新执行ExportDB.class文件,因为这里数据库中的表结构发生改变了。所以要重新生成表。
十三、测试加载
public void testLoad1(){
Session session=null;
try{
session=HibernateUtils.getSession();
Classes classes=(Classes)session.load(Classes.class,1);
Set students=classes.getStudents();
for(Iterator iter=students.iterator();iter.hasNext();){
Student student=(Student)iter.next();
System.out.println("students.name="+student.getName());
}
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
public void testLoad2(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
//注:load与get只能根据主键加载,根据别的字段是不可以的。
//第一个参数是相应的类
Classes classes=(Classes)session.load(Classes.class, 1);
System.out.println("classes.name="+classes.getName());
//拿出班级的学生,它是一个集合,然后一个一个输出学生名字。
Set<Student> students=classes.getStudents();
for(Iterator<Student> iter=students.iterator();iter.hasNext();){
Student student=iter.next();
System.out.println("student.name="+student.getName());
}
session.getTransaction().rollback();
}catch(Exception e){
e.printStackTrace();
}finally{
HibernateUtils.closeSession(session);
}
}
执行后SQL语句为:
先根据id到班级里面来查询
select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
班级查上来后,就可以把班级的学生查询上来。因为班级维护了一指向多的关系,所以它要找到这个关系字段,把班级的id拿来,然后它到t_student这张表中,找维护两个表关系的字段,就是classesid=这个班级的学生,把它一个一个的拿上来,它会自动地把这些学生放到学生集合里面。
select students0_.classesid as classesid1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classesid=?
再回想一下一对多,查询用户时,也可以把组加上来。之所以可以这样,是因为我们配置了关系,如果没有在映射文件里面配置这种关系,则hibernate就不会给我们加上来了。
十四、readme.txt文件
hibernate 一对多关联映射。(单向日葵 Classed----->Student)
一对多关联映射利用了多对一关联映射原理。
多对一关联映射,在多的一端加入一个外键,指向一的一端。但是它维护的关系是多指向一的。
一对多关联映射,在多的一端加入一个外键,指向一的一端。但是它维护的关系是一指向多的。
也就是说,一对多与多对一映射策略是一样的,只不过站的角度不同。
因为是在一的一端维护的关系(为什么知道是在一的一端维护的关系呢?
因为我们将关系的配置写到一的一端就是Classes.hbm.xml文件里面了。
缺点:在一端维护关系的缺点:
*如果将t_student表里的classesid字段设置为非空,则无法保存
*因为在一的一端维护的,所以刚开始建立时,学生是不知道她是哪个班级的。
所以一的一端要发出多余的update语句。
因为不是在student这一端维护关系(就像我没有记住你的电话号,所以找不到你),
所以student不知道自己是哪个班的。所以需要发出多余的update语句来更新关系。
基于以上的缺点,所以一对多关联映射通常要做成双向的。就可以克服这些缺点了。双向的返过来就是多对一。
为什么要做成双向的,最大的考虑,是将关系交给多的一端来维护,不让一的一端来做了。
就像不能让姚明记住十三亿人的名字一样,我们记住姚的就可以了。
原文地址:http://blog.sina.com.cn/s/blog_5fad23090100fct8.html
建立单元测试类One2ManyTest
package com.bjsxt.hibernate;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import junit.framework.TestCase;
public class One2ManyTest extends TestCase {
}
十二、测试save(保存)
一对多的存储方式应该与多对一不一样。一对多存储的应该是classes。因为班级与学生的关系是在classes类里面的students集合。所以应该是先有学生,把学生建立好之后,再放到Classes类的students这个集合里面。
1、testSave()方法内容如下:
public void testSave(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
Student student1=new Student();
student1.setName("菜10");
Student student2=new Student();
student2.setName("容祖儿");
Set<Student> students=new HashSet<Student>();
students.add(student1);
students.add(student2);
Classes classes=new Classes();
classes.setName("尚学堂");
classes.setStudents(students);
session.save(classes);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
当testSave()方法执行时,会出现这个org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.bjsxt.hibernate.Student 异常。
2、正确的保存testSave2()
public void testSave2(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
//先建立学生对象集合
Student student1=new Student();
student1.setName("菜10");
session.save(student1);
Student student2=new Student();
student2.setName("容祖儿");
session.save(student2);
//用泛型了
//因为班级里的学生是一个集合,所以要构造一个集合出来
Set<Student> students=new HashSet<Student>();
//向集合里面加数据
students.add(student1);
students.add(student2);
//要知道哪个学生所在的班级,要new 班级出来
Classes classes=new Classes();
classes.setName("尚学堂");
//这个班级里面有哪些学生,要用set方法加上去。
//这样这个尚学堂班级里面就有两个学生了
classes.setStudents(students);
session.save(classes);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
2.1执行后出现SQL语句:
insert into t_student (name) values (?)
只保存了学生的name,此时classesid字段值为null.
insert into t_student (name) values (?)
insert into t_classes (name) values (?)
hibernate又连接发了两条update,因为只有两个学生
update就是要把学生的classesid字段值更新上
根据学生id把classesid更新上。
也就是说,要由班级(一的一端)来维护这种关系:你菜10是我们班的,你容祖儿是我们班的。
在一的一端维护这种关系,会发现很多udpate。因为班级不知道会有多少学生。
就是说,由班级(一的端)主动记住这种关系
就如记人的名字一样,就如让姚明来记我们十三亿的人,这个关系要由姚来维护,
他要主动来记,把十三亿人的名字全部记下来。这肯定比较困难。因为由他一个人来更新,来记。
实际上,这种关系在多的一端来维护很容易,就如让我们记住姚明的名字很容易一样的。这是在一的端维护关系的一个缺点。另一个缺点是后面说的,如果在Student.hbm.xml映射文件中,将classesid字段设置为非空的话,则保存时会出错。
update t_student set classid=? where id=?
update t_student set classid=? where id=?
2.2执行结果数据库显示:
mysql> select * from t_classes;
+----+--------+
| id | name |
+----+--------+
| 1 | 尚学堂 |
+----+--------+
1 row in set (0.00 sec)
mysql> select * from t_student;
+----+--------+--------
| id | name |classesid
+----+--------+-------
| 1 | 菜10 | 1
+----+--------+-------
| 2 | 容祖儿 | 1
+----+--------+-------
1 row in set (0.00 sec)
2.3 我们现在分析一下数据库的结构,如这个测试方法,我们是先保存学生对象集合的。可是这时,这个学生对象里面只有名字与id,却没有classesid .可是表字段里是有classesid字段的。是在映射的时候加进去的。
可是如我们的测试方法,还是可以正确执行,班级里面可以加进去两个学生。 这是为什么呢?
原因是,我们的classesid字段是可以为空的。
也就是说,我们先把学生保存进去,可是这时 classesid 字段是没有值的。等到保存Classes时,再更新这个字段,将班级id值更新(update)上去。
如果我们在此Students.hbm.xml文件加上这样一条,让 classesid字段不能为空,再执行这个方法时,在存储时就会失败了,因为clssesid字段在保存时必须要值,不然就存不进去了。
<set name=”students”>
<key column=”classesid” not-null=”true”/>
<ont-to-many class=”com.bjsxt.hibernate.Student”/>
</set>
注:当修改完Students.hbm.xml文件时,要重新执行ExportDB.class文件,因为这里数据库中的表结构发生改变了。所以要重新生成表。
十三、测试加载
public void testLoad1(){
Session session=null;
try{
session=HibernateUtils.getSession();
Classes classes=(Classes)session.load(Classes.class,1);
Set students=classes.getStudents();
for(Iterator iter=students.iterator();iter.hasNext();){
Student student=(Student)iter.next();
System.out.println("students.name="+student.getName());
}
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
public void testLoad2(){
Session session=null;
try{
session=HibernateUtils.getSession();
session.beginTransaction();
//注:load与get只能根据主键加载,根据别的字段是不可以的。
//第一个参数是相应的类
Classes classes=(Classes)session.load(Classes.class, 1);
System.out.println("classes.name="+classes.getName());
//拿出班级的学生,它是一个集合,然后一个一个输出学生名字。
Set<Student> students=classes.getStudents();
for(Iterator<Student> iter=students.iterator();iter.hasNext();){
Student student=iter.next();
System.out.println("student.name="+student.getName());
}
session.getTransaction().rollback();
}catch(Exception e){
e.printStackTrace();
}finally{
HibernateUtils.closeSession(session);
}
}
执行后SQL语句为:
先根据id到班级里面来查询
select classes0_.id as id0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.id=?
班级查上来后,就可以把班级的学生查询上来。因为班级维护了一指向多的关系,所以它要找到这个关系字段,把班级的id拿来,然后它到t_student这张表中,找维护两个表关系的字段,就是classesid=这个班级的学生,把它一个一个的拿上来,它会自动地把这些学生放到学生集合里面。
select students0_.classesid as classesid1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classesid=?
再回想一下一对多,查询用户时,也可以把组加上来。之所以可以这样,是因为我们配置了关系,如果没有在映射文件里面配置这种关系,则hibernate就不会给我们加上来了。
十四、readme.txt文件
hibernate 一对多关联映射。(单向日葵 Classed----->Student)
一对多关联映射利用了多对一关联映射原理。
多对一关联映射,在多的一端加入一个外键,指向一的一端。但是它维护的关系是多指向一的。
一对多关联映射,在多的一端加入一个外键,指向一的一端。但是它维护的关系是一指向多的。
也就是说,一对多与多对一映射策略是一样的,只不过站的角度不同。
因为是在一的一端维护的关系(为什么知道是在一的一端维护的关系呢?
因为我们将关系的配置写到一的一端就是Classes.hbm.xml文件里面了。
缺点:在一端维护关系的缺点:
*如果将t_student表里的classesid字段设置为非空,则无法保存
*因为在一的一端维护的,所以刚开始建立时,学生是不知道她是哪个班级的。
所以一的一端要发出多余的update语句。
因为不是在student这一端维护关系(就像我没有记住你的电话号,所以找不到你),
所以student不知道自己是哪个班的。所以需要发出多余的update语句来更新关系。
基于以上的缺点,所以一对多关联映射通常要做成双向的。就可以克服这些缺点了。双向的返过来就是多对一。
为什么要做成双向的,最大的考虑,是将关系交给多的一端来维护,不让一的一端来做了。
就像不能让姚明记住十三亿人的名字一样,我们记住姚的就可以了。
原文地址:http://blog.sina.com.cn/s/blog_5fad23090100fct8.html
相关文章推荐
- Hibernate关联映射之-单向多对一关联(无连接表)
- hibernate之关于一对一单向,双向关联映射
- hibernate之关于一对多单向关联映射
- 【SSH进阶之路】Hibernate映射——一对一单向关联映射(五)
- Hibernate关系映射(5)_一对一单向联合主键关联
- Hibernate之对象关系映射07一对一多单向关联
- 【SSH进阶之路】Hibernate映射——多对一单向关联映射(四)
- Hibernate一对多单向关联和双向关联映射方法及其优缺点
- Hibernate(四):Hibernate映射——多对一单向关联映射
- Hibernate的关联映射---6.1.4: 单向n-n关联
- 我的Hibernate学习之旅(4)~多对一单向关联映射
- Hibernate 映射关系 ---One2Many单向关联
- Hibernate映射(一)------单向一对一主键关联
- Hibernate学习15 -- 关联映射5 -- 多对多关联1 -- 多对多关联单向
- Hibernate关系映射级别注解(一对一单向外键关联)
- hibernate映射关系之一对一单向主键关联
- 【SSH进阶之路】Hibernate映射——一对一单向关联映射(五)
- Hibernate高级实体关联映射之多值的实体关联(用组件类实现三重关联,单向导航)
- Hibernate之关于多对多单向关联映射
- Hibernate学习随笔-----关系映射(3)单向1-N关联