映射文件Order.hbm.xml
<hibernate-mapping package="cn.itcast.hibernate.domain">
<class name="Order" table="orders" lazy="false">
<id name="id" column="id" type="integer">
<!-- 主键生成策略 -->
<generator class="identity" />
</id>
<property name="orderno" column="orderno" type="string" length="20" />
<property name="price" column="price" type="float" />
<!-- 关联元素 -->
<many-to-one name="customer" column="cid" class="Customer" />
<!--多对一单向关联,是从Order出发 ,往Customer映射-->
</class>
</hibernate-mapping>
<set inverse="true">
inverse:反转,让缓存忽略的set的集合变化.set失去对关联关系的控制权.只按照对端的状态更新数据库.
级联保存:
保存Customer和Order对象时,如果只保存Order,不保存Customer,会出现临时对象异常(TransientObjectException),
可以设置many-to-one元素的cascade属性为save-update,hibernate会自动将和Order关联的Customer保存和更新了.
Order.hbm.xml
<many-to-one name="customer" column="cid" class="Customer" cascade="save-update" />
常见操作:
public void insert(){
Session s = sf.openSession();
Transaction tx = s.beginTransaction();
Customer c = new Customer();
c.setAge(12);
Order o = new Order();
o.setOrderno("No009");
o.setPrice(500f);
o.setCustomer(c);
s.save(c);
s.save(o);
tx.commit();
s.close();
}
我是先保存c好还是先保存o好呢??答案是先保存c好,因为如果先保存o,orders表有外键,会先把外键置为空,然后在保存c,最后知道外键值了还要有一步跟新oders表操作。
------------------------------------------------
②建立Customer到Order之间一对多关联
1.Customer.java
{ //建立从Customer到Order之间的一对多关联关系
private Set <Order> orders = new HashSet<Set>();
}
映射文件
<!-- 映射一对多关联关系(关联元素) -->
<set name="orders"> name是属性名称
<key column="cid" /> column是orders表的外键
<one-to-many class="cn.itcast.hibernate.domain.Order"/>
</set>
可以在set集合中设置属性cascade="save-update",我保存Customer的同时,也会把客户的订单保存起来。
cascade属性(包括set元素的cascade)都是指操作行为的传播,即对关联的对象是否也能执行相同的操作.
可以包括的级联操作有save-update,delete.
接下来是重点哦??想想,我们为什么还要建立从客户到订单的一对多关系呢??
建立一对多关系,也就是在Customer类中设一个Set <Order> order,的主要用途在于查询。当我们按照Customer的id 查询一个客户(Customer对象)时,就会也同时查询到,这个客户有多少个订单咯。。。
public void loadCustomer(){
Session s = sf.openSession();
Transaction tx = s.beginTransaction();
Customer c = (Customer)s.load(Customer.class,1);
Set<Order> orders = c.gerOrders();
for(Order o:orders){
System.out.println(o.getId());
}
tx.commit();
s.close();
}
// 保存
public void saveData(){
Session s = sf.openSession();
Transaction tx = s.beginTransaction();
Customer c = new Customer();
Order o = new Order();
//设置双向关系,保证程序健壮性
o.setCustomer(c);
c.getOrders().add(o);
s.save(c);
//s.save(o);
tx.commit();
s.close();
}
映射一对多双向关联关系时的注意点:
通常情况下:
1.
在one方,把<set>元素的inverse属性设为true,即<set inverse="true">,
inverse:反转,让缓存忽略set的集合变化。set失去对关联关系的控制权.只按照另一端的状态更新数据库.提高应用性能。
2.在one方,如果设把<set>元素的cascade="save-update"
<set name="orders" cascade="save-update" inverse="true">
这样做是为了,因为Customer和Order是一对多的关系,如果想保存Customer的同时,保存Order,就
要设置级联保存。总的来说通常情况下把<set>元素中,cascade="save-update" inverse="true"
理解<set>元素的inverse属性:举例
<set name="orders" cascade="save-update" inverse="true">
public void insert(){
Session s = sf.openSession();
Transaction tx = s.beginTransaction();
Customer c = new Customer();
c.setName("tomas");
Order order = new Order();
order.setCustomer(customer);//建立从Order到Customer的关联关系
//customer.getOrders.add(order);不建立从Customer到Order的关联关系
tx.commit();
s.close();
}
设置了Order的customer属性,Hibernate就会按照Order对象的变化来同步更新数据库。
而如果
public void insert(){
Session s = sf.openSession();
Transaction tx = s.beginTransaction();
Customer c = new Customer();
c.setName("tomas");
Order order = new Order();
//order.setCustomer(customer);不建立从Order到Customer的关联关系
customer.getOrders.add(order);建立从Customer到Order的关联关系
tx.commit();
s.close();
}
而如果仅设置了Customer的orders属性,由于<set>元素的inverse属性为true,因此Hibernate不会按照Customer对象的属性变化同步更新数据库。
补充:说白了吧。Customer 有orders 集合属性,而在Customer这边的映射文件中把<set>元素的inverse属性设为true,所以在保存Customer对象的时候,hibernate不会同步更新数据库.
引发数据错误。 hibernate不会按照Customer对象的属性变化而更新数据库.
所以我们在保存对象的时候,要尽量从Order一方下手,因为Order这边的映射文件
inverse是默认的false,保存order会同步更新数据库.
3.通常情况下,让one方的<set inverse="true">,而在many方,设置级联保存和更新,
<many-to-one name="customer" column="cid" class="Customer" cascade="save-update"/>
------------------------------------------------------------------------------------------
常见问题
PropertyValueException异常
<many-to-one>的not-null,有2个值,一个是true,一个是false.默认值是false,就是外键可以为空,
而在表中如果设了外键不可以为空的话,我又在<many-to-one not-null="true">就是可以不为空
我用session只保存了Order,而没有先保存Customer的话,Hibernate会向orders表中的插入一条记录,而且把外键设为null,这样就矛盾了,所以会报PropertyValueException异常。
映射组成关系
public class Customer{
id,
name
}
public class Address{
private String province;
private String city;
private String street;
private String zipcode;
}
-----------------------------------------------------------------------------------------------------------------------------
③一对一映射
㈠外键关联 和多对一映射方式类似,通过多对一来模拟的
外键具有唯一性
public class User{
private Integer id;
private String name;
private Adder adder;
}
public class Addr{
private Integer id;
private String province;
private User user;
}
Addr.hbm.xml
<class name="Addr" table="addr_fk" lazy="false">
<id name="id" column="id" type="integer">
<generator class="identity"/>
</id>
<property name="province" column="province" type="String" length="20">
<!--关联元素,唯一性约束-->
<many-to-one name="user" column="userid" class="User" unique="true"/>
</class>
User.hbm.xml
<class name="User" table="addr_fk" lazy="false">
<id name="id" column="id" type="integer">
<generator class="identity"/>
</id>
<property name="name" column="name" type="String" length="20">
<!--关联元素,映射User到Addr的一对一关联,property-ref属性参考,指定对端的关联属性-->
<one-to-one name="addr" property-ref="user"/>
</class>
-----------------------------------------------------------------------------------------
㈡主键关联
User.hbm.xml
<class name="User" table="user_pk" lazy="false">
<id name="id" column="id" type="integer">
<generator class="identity"/>
</id>
<property name="name" column="name" type="string" length="20"/>
<one-to-one name="addr" class="Address"/>
</class>
Address.hbm.xml
<id name="id" colunm="id" type="integer">
<generator class="foreign"/> 从外部提取 ,让地址表的主键跟随用户表的主键保持一致
<param property="user"> </param>
</id>
<one-to-one name="user" class="User" constrained="false"/>
我的id值是从外部的一个属性提取的 user属性
constrained:受到约束的,user!=null且 user.id!=null
----------------------------------------------------------------------------------------
④多对多关联
public class Teacher{
private Integer id;
private String teaNo;
private Set<Student> students = new HashSet<Student>();
}à一个教师有多个学生
//集合中的每个元素类型都是学生
public class Student{
private Integer id;
private String stuName;
private Set<Teacher> teachers = new HashSet<Teacher>();
} à一个学生有多个教师,两边都是一对多
-----------------------------------------------------------------------------------------
Teacher.hbm.xml
<!--映射多对多关系,要指定中间表links-->
<!--多对多关系要维护中间表,如果两边都维护的话,导致记录的冲突,所以一定要把一端的维护权消除-->
<set name="students" table="links" inverse="true">
<key column="tid"/>
<many-to-many class="Student" column="sid"/我要想查一个教师有几个学生,所以一定要查sid>
</set>
Student.hbm.xml
<set name="teachers" table="links" >
<key column="sid"/>
<many-to-many class="Teacher" column="tid"/>
</set>
-----------------------------------------------------------------------------------------
public class Teacher {
private Integer id;
private String teaNo;
private Set<Student> students = new HashSet<Student>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getTeaNo() {
return teaNo;
}
public void setTeaNo(String teaNo) {
this.teaNo = teaNo;
}
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
}
//用一个可变参数往集合中添加元素
public void addStudent(Student... students){
for(Student s : students){
getStudents().add(s);
}
}
}
-----------------------------------------------------------------------------------------
public void save(){
t1.addStudent(s1,s2,s3);
s2.addTeacher(t1,t2);
}
-----------------------------------------------------------------------------------------
⑤映射自关联 和多对一类似
parentid 引入上边的主键值
public calss Area{
private Integer id;
private String name;
//建立到上级的多对一关系
private Area parentArea;
//建立到下级的一对多关系
Private Set<Area> children =new HashSet<Area>();
}
Area.hbm.xml
//建立自关联的多对一关系
<many-to-one name="parentArea" column="parentid" class="Area"/>
//建立自关联的一对多关系
<set name="children" inserse="true">
<key colunm="parentid">
<one-to-many class="Area">
</set>
相关推荐
只是一份非常珍贵的hibernatePPT教程。从第一个hibernate的简介到hibernate的完全实践都非常详细,按照课件一步步的操作。你就可以快速掌握真正的企业级hibernate开发实践。是非常珍贵的学习资料
hibernate 注解 annotation 教程
Hibernate经典版 通过图解让你轻松学会Hibernate
本人精心搜集了学习hibernate的资料,一些是我以前学习用的,一些是新搜集的 资料。 <br>搜集清单和说明 1:hibernate学习源码,这是我以前做练习的代码,希望对感兴趣的朋友 有些帮助。 2:...
hibernate教程,很详细的hibernate教程,很详细的hibernate教程,很详细的hibernate教程,很详细的hibernate教程,很详细的hibernate教程,很详细的hibernate教程,很详细的hibernate教程,很详细的hibernate教程,...
总的来说,【hibernate个人学习笔记完整版】是全面学习Hibernate的理想资源,无论你是初学者还是有经验的开发者,都能从中获取宝贵的知识,提升你的ORM技能。通过系统的学习和实践,你将能够自如地运用Hibernate解决...
hibernate3.3.2官方完整版,内含java调用完整教程
hibernate 教程 源代码, 包括关系映射,hql和帮助文档
Hibernate教程01_Hibernate的HelloWorld及基本配置 http://blog.csdn.net/e421083458/article/details/8794127 该源码为Hibernate教程配套源码
Hibernate教程(非常详细)
Hibernate 完整使用教程 Hibernate 是一种流行的开源持久层框架,允许开发者使用面向对象编程语言来访问关系数据库。下面是关于 Hibernate 的详细知识点: Hibernate 介绍 Hibernate 是一个开源的持久层框架,它...
Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以...
Hibernate教程Hibernate教程Hibernate教程Hibernate教程Hibernate教程
本教程将引导你从零基础开始,逐步深入理解并掌握Hibernate的核心概念和技术。 在【入门阶段】,你将学习到: 1. Hibernate概述:了解ORM的概念,以及Hibernate如何解决传统JDBC编程中的问题。 2. 安装与配置:设置...
Hibernate Spatial 4 教程 Hibernate Spatial 是一个基于 Hibernate 或 JPA 的空间几何对象数据库操作框架,提供了实现空间几何对象数据库操作的方法和配置说明。 一、 Hibernate Spatial 4 简介 Hibernate ...
Java框架中关于hibernate的基础学习
教程包含了hibernate4 的新特性; hibernate4和hibernate3的区别; hibernate4和spring3.2整合的问题; 文档以pdf,htm格式呈现给开发者; 详细教了hibernate4;
**Hibernate 教程:带你入门持久化框架** Hibernate 是一个流行的开源对象关系映射(ORM)框架,它为 Java 应用程序提供了便捷的数据持久化服务。本教程将引导你逐步了解 Hibernate 的基本概念、安装配置以及核心...
通过学习这些资料,你将能够有效地掌握Hibernate框架,实现Java对象与数据库之间的无缝转换,提升你在Java开发中的数据库操作能力。无论是对于初学者还是经验丰富的开发者,这都是一份宝贵的资源,帮助你更好地理解...