一对多关联映射总结---hibernate

一对多关联映射(one-to-many单向)

一、对象模型
在对象模型中一对多关联映射,通常在一的一端要使用集合来表示关联关系。
比如班级-->学生就是一个典型的一对多的关系。

一对多关联映射总结---hibernate


说明:之所以在一的一端需要持有对多的一端集合引用,是为了方便在加载班级的时候同时加载对应班级
下面的学生。

二、原理

【实现原理】先有班级[one]后有学生[many],实现一对多需要在多的一端建立外键指向一的端

one-to-many单向:就是能从
Cleasses中访问到对应的学生,反之无效.

三、面试题

【面试题】多对一与一对多的区别与联系?

一对多关联映射利用了多对一关联映射原理
多对一关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是多指向一(Person---Group)
一对多关联映射:在多的一端加入一个外键指向一的一端,它维护的关系是一指向多(Classes---Students)
总结:也就是说一对多和多对一的映射策略是一样的,只是角度不同

四、业务模型(实体类)


ClassesPOJO.java


private int id;


private String name;


private Set students;
//一指向多
StudentPOJO.java


private int id;


private String name;

五、配置文件

(1)一的一端(Classes.hbm.xml)的配置:需要加入<set>标签

 

<set name="students(Classes实体类中 Set接口类型的变量名 )">
<key column="classid(对应于多的一端在数据库中的外键 )"/>
<one-to-many class="多的一端实体类的路径 ">
</set>


<hibernate-mapping package="com.tarena.hibernate">
<class name="Classes" table="t_classes">
<id name="id">

<generator class="native"/>
</id>
<property name="name"/>


<set name="students">
<key column="classesid"/>
<one-to-many class="Student"/>


</set>


</class>
</hibernate-mapping>

(2)多的一端(Student.hbm.xml)的配置:
<hibernate-mapping>
<class name="com.bjsxt.tarena.Student" table="t_student">
<id name="id">

<generator class="native"/>//ID自动增长
</id>
<property name="name"/>
</class>
</hibernate-mapping>

六、代码测试


(1)save操作()
存储策略:因为在 Classes实体类(One)中存在一个对 Student实体类的 Set集合引用,所以要先存
Student对象,然后在为 Student分配班级。


public void testSave1() {
Session session = null;

try
{

session = HibernateUtils.getSession();
session.beginTransaction();


//创建学生1

Student student1 = new Student();
student1.setName("张三" );
session.save(student1);//记得要先保存学生信息到数据库


//创建学生2


Student student2 = new Student();
student2.setName("李四" );
session.save(student2);//记得要先保存学生信息到数据库


//将学生放入Classes实体的Set集合


Set students = new HashSet();

students.add(student1);
students.add(student2);


//创建学生对象并把学生集合在放入到班级对象中


Classes classes = new Classes();
classes.setName("sd0801");//为班级分配学生
classes.setStudents(students);
//保存班级对象的同时也把对应班级的学生存入数据库
session.save(classes);
session.getTransaction().commit();
}catch(Exception e)
{
e.printStackTrace();
session.getTransaction().rollback();

}finally
{
HibernateUtils.closeSession(session);
}
}
说明:(1)上面方法之所以可以正确保存学生对象,是因为 t_students表中的外键 classesid约束允许为空,
假如此外键设置非空了将会插入数据库的时候报错。

(2)上面代码的插入数据库的流程:先存入学生对象(id自增,name程序设定,classesid为空),当创建完班
级对象后,在象数据库存入班级信息的时候在同时把班级的 id做为外键同时也为 t_students表的 classesid
存入对应班级的 id(此时 Hibernate会发出 update语句),由此可得出结论:假如同时批量创建学生对象,然
后为多个学生分配班级,此时 hibernate会发出多个 update语句去为 t_students表外键 classesid赋值,所
以影像了程序的性能。
(2)Load操作(加载班级看对应班级的学生信息)
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());

}

session.getTransaction().commit();
}catch(Exception e)
{
e.printStackTrace();
session.getTransaction().rollback();

}finally
{
HibernateUtils.closeSession(session);
}
}

在一一端维护关系的缺点:
*
如果将 t_student表里的 classesid字段设置为非空,则无法保存
*
因为不是在 student这一端维护关系,所以 student不知道是哪个班的,所以需要发出多余的
update语句来更新关系(所以建议采用下面的双向关联一对多)一对多关联映射(one-to-many双向(常用))

一、如何实现一对多双向(实现原理)
(1)在一的一端的实体类中加入对多的一端的 Set接口引用
如:
private Set students;
//一指向多(Set)
(2)在多的一端的实体类中加入对一的一端的实体引用
如:
private Classes classid;
//多指向一(vo)
对象模型实例图如下:

一对多关联映射总结---hibernate

 

二、实体类映射的配置文件
Classess.hb.xml:
<hibernate-mapping>
<class name="shuangXiang.pojo.Classess" table="t_classes">

<id name="id" column="id" type="java.lang.Integer">

<generator class="native"/>

</id>
<set name="students" inverse="true" cascade="all">

<!--对应Classes实体类中private Set students; -->
<key column="classid"/><!--对应于多的一端在数据库中的外键-->
<one-to-many class="shuangXiang.pojo.Student"/>

<!--多的一端实体类的路径-->
</set>
</class>
</hibernate-mapping>

Student.hb.xml:


<hibernate-mapping>
<class name="shuangXiang.pojo.Student" table="t_student">
<id name="id" column="id" type="java.lang.Integer">

<generator class="native"/>
</id>
<property name="name" column="name" type="java.lang.String"/>
<many-to-one name="classess" column="classid"></many-to-one>
<!--many-to-one会用name属性的值来生成一个外键指向一的一端,维护多对一的关系,但是在一对多双
向关联的时候必须用column属性把name属性的值绑定在一起(此时classid对应于Classes.hbm.xml文件中<key
column="classid"/>;)
-->
</class>
</hibernate-mapping>

三、代码测试


public void testSave02(){
session = HibernateUtils.getSession();
session.beginTransaction();
//先创建好班级
Classess classess = new Classess();
classess.setName("0802");
session.save(classess);

//按需要给对应的学生分配班级

Student student = new Student();

student.setName("李四" );
student.setClassess(classess);
session.save(student);
session.getTransaction().commit();
}

public void testLoad(){
Session session = HibernateUtils.getSession();
Student stu = (Student)session.load(Student.class,4);
System.out.println("单向获取的姓名:" +stu.getName());
System.out.println("单向获取的班级:" +stu.getClassess().getName());
Classess classes = (Classess)session.load(Classess.class,4);
System.out.println("获取班级姓名:" +classes.getName());


}
四.相关总结

(1)hihernate一对多关联映射(双向 Classes<----->Student)
(2)一对多双向关联映射:
*在一一端的集合上使用<key>,在对方表中加入一个外键指向一一端
*在多一端采用<many-to-one>
注意:<key>标签指定的外键字段必须和<many-to-one>指定的外键字段一致,否则引用字段的错误
如果在”一“一端维护一对多关联关系,hibernate会发出多余的 udpate语句,所以我们一般在多的一端来维护关联关系

(3)关于 inverse属性:
inverse主要用在一对多和多对多双向关联上,inverse可以被设置到集合标签<set>上,
默认 inverse为 false,所以我们可以从”一“一端和”多“一端维护关联关系,
如果设置成 inverse为 true,则我们只能从多一端来维护关联关系
注意:inverse属性,只影响数据的存储,也就是持久化
(4)inverse和 cascade
*inverse是关联关系的控制方向
*cascade操作上的连锁反应

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值