1).级联添加:
我们有设置order的映射文件的many-to-one,在此我们也必须设置customer的set元素:
<set name="orders" cascade="save-update" lazy="false">
<key><column name="cid"></column></key>
<one-to-many class="cn.itcast.cc.hibernate.persistence.Order"/>
</set>
|
name:设定待映射持久化类的属性名。
cascade:设定级联操作的程度。
key子属性:设定与所关联的持久化类对应的标的外键。
one-to-many子属性:设定所关联的持久化类。
我们可以设置cascade的值为“delete”这样在删除一个客时,也可以自动删除与客户级联的orders。
cascade属性值
|
描述
|
none
|
忽略关联对象,默认值
|
save-update
|
保存或更新当前对象时,级联保存关联的临时对象,更新关联的游离对象。
|
delete
|
删除对象时,级联删除关联的对象。
|
all
|
包含save-update和delete的行为。
|
delete-orphan
|
删除所有和当前对象解除关联关系的对象。
|
all-delete-orphan
|
包含all和delete-orphan的行为。
|
添加代码:
customer.getOrders().add(order);
|
此时我们只保存customer或order对象,hibernate都可以将两个对象的数据保存到对应的表中。
注意:如果映射文件没有设置“cascade="save-update"”属性,则保存失败并抛异常!
2).级联删除:
我们调用session.delete(customer);方法时会一同删除customer对象的orders吗?不会!如果我们希望能够删除,我们必须设置Set元素的属性:cascade="delete"。
那如果我删除一个order,能自动删除对应的customer吗?你想可以吗?这本身就不符合业务逻辑!
3).Set集合的inverse属性:
这个属性十分重要,涉及到hibernate缓存监控技术。(hibernate缓存监控技术在后面会有介绍)。Inverse属性使得,如果持久化对象一旦发生改变就自动更新数据表中的记录。(持久化对象后面会有介绍)通过load、save、update返回或设置的对象都是持久化对象,这些对象一起发生改变,比如set了一个新值,hibernate就会自动将新值更新到数据库中。当调用了session.close方法是,这些持久化对象就不存在了!
结论:
1.在映射一对多的双向关联关系时,应该在one方把inverse属性设为true,这可以提高性能。
2.在建立两个对象的关联时,应该同时修改关联两端的相应属性:
Customer.getOrders().add(order);
Order.setCustomer(customer);
这样才会使程序更加健壮,提高业务逻辑层的独立性,使业务逻辑层的程序代码不受Hibernate实现类的影响。同理,当删除双向关联的关系时,也应该修改关联两端的对象的相应属性:
Customer.getOrders().remove(order);
Order.setCustomer(null);
一对一关联与多对多关联,我在此就不做总结了。把多对一和一对多搞明白了,这些就容易了!
四、操纵持久化对象
在hibernate中有三个缓存:一个是普通的SessionFactory的缓存,用来存储映射文件和SQL查询语句。一个是Session的缓存(一级缓存)用来存放持久化对象。一个是二级缓存(这个还没学)。
操纵持久化对象,玩的就是一级缓存。Session接口提供save、update、delete、load、get方法,这些方法设置或读取的对象被保存在一级缓存中,这些对象被称为持久化对象。我们前边提到的所有持久化对象,必须是保存在缓存中的对象。
1.JAVA对象在JVM中的生命周期
我们知道JAVA有自己的垃圾回收器机制,当一个对象不再被直接或间接的引用时,它就是垃圾对象。垃圾回收会将它释放掉。我们new出来的java对象被放在堆中,而对象的引用放在栈中。创建一个java对象JVM需要做三步,比如 String str = new String();:
1. new String()对象放在堆中。
2. str放在栈中。
3. 将str指向堆中的对象。
如:
1. String str1 = new String();
2. String str2 = str1;
3. str1 = null;
4. str2 = null;
请问放在堆中的对象何时被销毁?第三步吗?No!是第四步。这个对象从第1步“出生”,到第4步执行结束后“死亡”。
2.理解session的缓存
持久化对象被保存在缓存里,这么做有什么好处?
1. 减少访问数据库的频率。
2. 保证缓存中的对象与数据库中的记录保存同步。(监控技术)
3. 当缓存中的持久化对象之间存在循环关联关系时,Session会保证不出现访问对象图的死循,还以及由死循环引起的JVM堆栈溢出异常。
监控技术是如何实现的?session保存在缓存中的持久化对象,实质上是保存了对象的引用。那么同时与这个引用对应一个持久化对象的clone对象。Session监控就是将持久化对象与在缓存中的clone对象进行对比,如果发生改变就自动对数据库进行相应的操作。这样就保持了持久化对象与数据库记录的同步。
Session在清理缓存时,按照以下顺序执行sql语句。
1.按照应用程序调用save()方法的先后顺序,执行所有的对实体进行插入的insert语句。
2.所有对实体进行更新的update语句。
3.所有对实体进行删除的delete语句。
4.所有对集合元素进行删除、更新或插入的sql语句。
5.执行所有对集合进行插入的insert语句。
6.按照应用程序调用delete()方法的先后执行。
默认情况下:
1.当应用程序commit()方法的时候,先清理缓存,然后在向数据库提交事务。
2.当调用find()或iterator()时,如果对象属性发生变化,会先清理缓存,以保证查询结果能够反映持久化对象的最新状态。
3.显式调用flush()。
3.操作Session缓存的重要方法:
Session的清理模式:“session.setFlushMode(FlushMode.AUTO);”
清理缓存的模式
|
Session的查询方法
|
事务的commit()
|
Session的Flush()
|
FlushMode.AUTO
|
清理
|
清理
|
清理
|
FlushMode.COMMIT
|
不清理
|
清理
|
清理
|
FLushMode.NEVER
|
不清理
|
不清理
|
清理
|
FlushMode.NEVER 模式受主键影响,当主键为identity时,受底层数据库影响所以NEVER无效。如果为increment时,由于这个主键不受底层数据库的影响,所以NEVER有效!
清理方法:
Session.flush();//清理、刷出数据库与缓存同步,但不提交事务。
Session.refresh();//刷新。让缓存与数据库同步。
Session.clear();//清空。清空缓存中的引用。
4.hibernate中Java对象的状态:
临时状态(transient):用new语句创建,没有被持久化(没有调用Session对方法),不处于session中,该对象成为临时对象。
持久化状态(persistent):已经被持久化,加入到session的缓存中。该状态的对象为持久化对象。
游离状态(detached):已经被持久化,但不处于session中(seesion清空或被delete)。该状态的对象为游离对象。
如:
程序代码
|
生命周期
|
状态
|
tx = session.beginTransaction();
Customer c = new Customer(“Tom”,new HashSet);
|
开始生命周期
|
临时状态
|
Session.save(c)
|
处于生命周期中
|
转变为持久化状态
|
Long id=c.getId();
c = null;
Customer c2 = (Customer)session.load(Customer.class,id);
tx.commit();
|
处于生命周期中
|
处于持久化状态
|
session.close();
|
处于生命周期中
|
转变为游离态
|
c2,getName();
|
处于生命周期中
|
处于游离态
|
c2 = null;
|
结束生命周期
|
结束生命周期
|
1).临时对象特征
l 不处于session中,不被任何session关联。
l 数据库中没有对应的记录。
l 以下情况,对象进入临时状态:
1. new语句刚创建了一个对象。
2. session的delete方法使持久化对象或游离对象转变为临时对象,对于游离对象,该方法从数据库中删除记录,对于持久化对象,该方法从数据库中删除记录,还要删除缓存中的对象。
临时对象判断法:
1.OID为null。
2.具有version属性并取值为null。
3.在映射文件中为<id>元素设置了unsaved-value属性,并且OID属性取值与属性匹配。
4.在映射文件中为<version>元素设置了unsaved-value属性,并且version属性取值与属性匹配。
5.自定义了Interceptor实现类,并且isUnsaved方法返回Boolean.true。如果id的类型为long,则默认值为0,此时需要在配置文件中设置id的unsaved-value为0。
2) . 持久化对象特征
l 位于一个session缓存中,总是被一个session关联。
l 持久化对象和数据库记录相对应。
l 清理缓存时,会根据对象属性变化,同步更新数据库。
l save把临时对象转变为持久化对象。
l load或find或get返回的对象总是持久化状态。
l find方法返回的list存放的都是持久化对象。
l update、save、SaveOrUpdate和Lock方法使游离对象装变为持久化对象。
在实际的应用程序中应该避免一个java对象被多个session实例关联,会导致重复执行sql语句,并且极容易出现一些并发问题。
3).游离对象特征
l 不再位于session的缓存中,游离对象不被session关联。
l 游离对象由持久化转变过来的,因此在数据库中可能还存在与它对应的记录(前提条件是没有其他程序删除了这条记录)。
l close方法使缓存被清空,缓存中的所有的对象都变为游离对象。如果没有引用他们的话,他们就会结束生命周期。
l evict方法从缓存中删除一个持久化对象,使他变为游离态对象。当缓存中保存了大量的持久 化对象时,会消耗许多内存空间,使用该方法删掉一些对象来节省空间。
5.操作持久化对象的方法
1).save:
l 对象加入缓存,成为持久化对象。
2). update:
l 将游离对象转变为持久化对象。不论对象属性是否发生变化,该方法都会执行update操作。如果希望仅当属性变化时才执行update语句的话可进行如下配置:
<class name=“…”
table=“…”
select-before-update=“true”>
3). saveOrUpdate:
l 该方法同时包含save和update方法,如果参数是临时对象就用save方法,如果是游离对象就用update方法,如果是持久化对象就直接返回。
4) .load和get:
l 从数据库加载指定的OID持久化对象。
l 如果数据库中不存在该记录时,load方法会抛出异常,而get方法返回null。
5). delete
l 如果参数是持久化对象,就执行一个delete语句。若为游离对象,先使游离对象被session关联,使他变为持久化对象,然后计划执行一个delete语句。
6.与触发器协同工作
触发器的行为导致缓存与数据库中的数据不一致。解决办法是执行完操作后,立即调用session的flush方法和refresh方法,迫使缓存与数据库同步。
Session的update操作方法盲目的激活触发器,如果游离状态的对象的属性和数据库一致,则更新操作是多余的。
<spa
分享到:
相关推荐
传智播客 hibernate PPT 很经典
标题"传智播客hibernate源码"暗示了这是一个关于Hibernate框架的源代码学习资源,可能包含了对Hibernate框架内部机制的深入解析,以及如何在实际项目中应用Hibernate的相关示例。 描述中的内容重复,进一步确认了这...
传智播客Hibernate课件.ppt
传智播客hibernate教程.ppt传智播客hibernate教程.ppt传智播客hibernate教程.ppt传智播客hibernate教程.ppt传智播客hibernate教程.ppt
【标题】"01_传智播客hibernate教程_hibernate介绍与动手入门体验" 涉及的是一门关于Hibernate的初学者教程,旨在帮助开发者了解并掌握这一流行的Java对象关系映射(ORM)框架。Hibernate是Java开发中的一个关键工具...
【标题】"传智播客 Hibernate源码"涵盖了关于Hibernate框架的深度学习和解析,它是一个流行的Java持久层框架,用于简化数据库操作。通过研究源码,开发者可以深入理解其内部工作原理,提升数据库管理效率,并能更好...
【传智播客李勇hibernate PPT】是一份由知名教育机构传智播客推出的关于Hibernate框架的培训资料,由讲师李勇精心制作。这份PPT详细讲解了Hibernate在实际开发中的应用,旨在帮助学员深入理解并掌握这一强大的Java...
【标题】"传智播客hibernate ppt"是一份由知名教育机构传智播客推出的关于Hibernate框架的培训教程,由资深讲师李勇主讲。这个PPT内容经典,深受学习者好评,旨在帮助开发者深入理解和掌握Hibernate这一强大的Java...
传智播客的Java Web课程的ppt关于数据库持久的框架Hibernate
【传智播客 Hibernate 教程】 传智播客是一家知名的IT教育机构,其课程涵盖了各种编程技术,包括Java中的ORM框架Hibernate。本教程主要基于传智播客的PPT资料,旨在帮助学习者深入理解Hibernate的核心概念和使用...
本资料主要基于“传智播客hibernate源码.rar”进行深入剖析,旨在帮助你理解Hibernate的核心机制,提升你的编程能力。 一、Hibernate简介 Hibernate是一个开放源代码的对象关系映射(ORM)框架,它对JDBC进行了非常...
传智播客Hibernate课件
【标题】:“02_传智播客hibernate教程_hibernate入门案例的细节分析” 在本教程中,我们将深入探讨Hibernate,一个流行的Java对象关系映射(ORM)框架,它简化了数据库操作,使开发者可以更加专注于业务逻辑而不是...
传智播客 hibernate 完全学习文档,没有更好
传智播客李勇hibernate源码1-20课,目录如下:01_hibernate介绍与动手入门体验;02_hibernate入门案例的细节分析; 03_hibernate入门案例的代码优化; 04_Session接口及get|load|persist方法 05_实体对象的三种状态...
【传智播客李勇hibernate】课程详解了ORM框架Hibernate的核心概念和技术,适合初学者和想要深入了解Hibernate的开发者。以下是对课程内容的详细解析: 1. **引入ORM框架**: - 阻抗不匹配:由于Java是面向对象的...
《传智播客2016 Hibernate框架学习笔记》是一份详实的教程,旨在帮助初学者和进阶者深入理解和掌握Hibernate框架。该资源包含了四天的学习内容,分别是day01、day02、day03和day04,涵盖了从基础到高级的多个主题。...