Hibernate 知识点小结Word文档格式.docx
- 文档编号:22823085
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:15
- 大小:21.80KB
Hibernate 知识点小结Word文档格式.docx
《Hibernate 知识点小结Word文档格式.docx》由会员分享,可在线阅读,更多相关《Hibernate 知识点小结Word文档格式.docx(15页珍藏版)》请在冰豆网上搜索。
#8221;
的用户记录
TUseruser=newTUser();
user.setName("
tina"
);
session.save(user);
Session具有一个缓存,位于缓存中的对象出于持久化状态,它和数据库中的相关记录对应,
Session能够在某些时间点,按照缓存中持久化对象的属性变化来同步更新数据库,这一过程被称为清理缓存.
理解Session:
首先理解,当应用程序通过new语句创建一个java对象时,jvm会为这个对象分配一块内存空间,只要这个对象被引用变量引用,它就一直存在于内存中.如果这个对象不被任何引用变量引用,它就结束生命周期,此时jvm的垃圾回收器会在适当的时候回收它占用的内存.
java的集合(list,set,map)的一个重要特征是:
集合中存放的是java对象的引用.
当向集合中添加一个对象时,其实是把这个对象的引用添加到集合中;
如果希望一个java对象一直出于生命周期中,就必须保证至少有一个变量引用它,或者在一个java集合中存放了这个对象的引用.
在session接口的实现类sessionImpl中定义了一系列的java集合,这些java集合构成了session的缓存.例如:
//Map集合中的键对象代表持久化对象的OID,值对象代表持久化对象
PrivatefinalMapentitiesByKey;
&
#8230;
EntitiesByKey.put(key,object);
//向session的缓存中加入一个持久化对象
&
EntitiesByKey.remove(key);
//从session的缓存中删除一个持久化对象
EntitiesByKey.clear();
当session的save()方法持久化一个User对象时,user对象被加入到session的缓存中,以后即使应应用程序中的引用变量不再引用user对象,只要session的缓存还没有被清空,user
对象仍然处于生命周期中.当session的load()方法试图从数据库中加载一个user对象时,session先判断缓存中是否已经存在这个user对象,如果存在,就不需要再到数据库中检索.
Session的缓存两大作用:
(1)减少访问数据库的频率.应用程序从内存中读取持久化对象的速度显然比到数据库中查询数据的速度快多了,因此session的缓存可以提高数据访问的性能;
(2)保证缓存中的对象与数据库中的相关记录保持同步.位于缓存中的对象被称为持久化对象.当缓存中持久化对象的状态发生了变化,session并不会立即执行相关的SQL语句,这使得session能够把几条相关的SQL语句合并为一条SQL语句,以便减少访问数据库的次数,从而提高应用程序的性能.
例如以下程序代码对user的name属性修改了两次:
T=session.beginTransaction();
Useruser=(User)session.load(User.class,newLong
(1));
User.setName(&
jack&
tom&
T.commit();
当session清空缓存时,只需执行一条update语句:
Updatet_usersetname=&
whereid=1;
注:
当session加载了user后,会为user对象的值类型的属性复制一份快照.当session清理缓存时,通过比较user对象的当前属性与它的快照,session能够判断user对象的那些属性发生了变化.
在默认情况下,session会在下面的时间点清理缓存
1)当应用程序调用commit()方法的时候,commit方法先清理缓存,然后再向数据库提交事务;
2)当应用程序显示调用session的flush()方法的时候.
Session进行清理缓存的例外情况是,如果对象使用native生成器来生成oid,那么当调用session的save方法保存对象时,会立即执行向数据库中插入该实体的insert语句.
注意:
session的commit方法和flush方法的区别,flush方法进行清理缓存的操作,执行一系列SQL语句,但不会提交事务;
commit方法会先调用flush方法,然后提交事务.
提交事务意味着对数据库所做的更新被永久保存下来.
默认flush的时机:
1)提交commit时会隐含的进行flush;
2)直接调用flush;
3)执行某些查询之前hibernate会自动进行flush;
hibernate在用oid去查询时,不一定去数据库里查,先从session中查;
可以通过session的setFlushMode方法设置清理缓存的时间点;
FlushMode.AUTO,
FlushMode.COMMIT,FlushMode.NEVER,用来约束session的查询方法,commit方法,flush方法是否清理缓存;
第一个是默认值,保证在整个事务中,数据保持一致.
Cmmit模式.可以避免在执行session的查询方法时先清理缓存,提高应用程序的性能.
二,一对一,一对多的关系
1,id的生成方式;
7种,看第二天的笔记;
lt;
idname="
id"
column="
gt;
generatorclass="
seqhilo"
!
--这时默认的,selecthibernate_sequence.nextvalfromdual;
--&
--这里不指定参数的话同上,也可以指定自定义的sequence--&
sequence"
paramname="
person_seq&
/param&
/generator&
/id&
用的比较多的是native,sequence;
2,一对一关系,唯一外键,共享主键;
1)唯一外键:
在Account.xml中:
账户表维护的是关系的主键;
one-to-onename="
addr"
property-ref="
act"
cascade="
all"
/&
在Address.xml中:
维护的是关系的外键,代表多;
many-to-onename="
fid"
unique="
true"
/&
fid是Address表里的外键,关联到Account的主键aid;
唯一外键表结构:
createtableln_address(
oidnumber(20)primarykey,
postcodevarchar2(20),
cityvarchar2(20),
streetvarchar2(30),
fidnumber(20)notnullunique,//fid外键引用ln_account(aid)
constraintaccount_addressforeignkey(fid)
referencesln_account(aid)
);
createtableln_account(
aidnumber(20)primarykey,
actNovarchar(100)notnull,
ownervarchar(20)notnull,
balancenumber(20,2),
2)共享主键:
account的xml文件:
表示对方的主键就是外键
address的xml文件:
oid"
--既是主键又是外键;
值是从它引用的表得到的;
foreign"
--表示主键引用的是别的表--&
property"
account&
account"
constrained="
constrained="
;
//acct所对应的类型的表,account表,对我现在的表形成了外键约束;
//account表的主键对address表的主键形成了外键约束;
表结构:
address的主键又是外键和account的值一致;
constraintaccount_address2foreignkey(oid)
3,一对多的关系:
(1)user的xml文件:
(一的一方,有一个account的set集合)
setname="
accounts"
inverse="
keycolumn="
/key&
one-to-manyclass="
Account"
/set&
1、集合里存的是PO,集合代表一对多;
并且是关联属性;
one-to-many&
2、class="
;
说明集合中的PO类型;
因为泛型只是编译时有效,虚拟机看不到,所以还要说明类型;
3、key标签说明的是,关系的另一方(Account)表中与本表关联的外键字段的名字;
关系的维护权:
一对多的关系中,在一的一方写上inverse="
将关系的维护权放在多的一方;
false"
//默认的,User维护关系,存user时,会先存account;
这时存account时,account有外键字段,先插入三条account语句,fid=null;
再插入user,并且要更新account的外键字段;
//User放弃维护关系,会先存user,user的oid先算出来,然后再存account,fid就有值了;
1)、防止外键为空;
把关系的维护交给多的一方;
2)、防止n+1次更新;
如果为false;
user.add(account);
s.saveOrUpdate(user);
更新user时会把集合的元素更新一遍;
再更新user;
如果为true;
存account时会先存user,再把自己存上就行了;
(2)account的xml文件:
多的一方,有一个user属性,维护外键;
propertyname="
actNo"
not-null="
//自动建表时加上约束
user"
save-update"
:
帐户保存和更新时更新用户,但删帐户时不能删用户;
三,Hibernate应用中java对象的状态:
transient:
暂态,瞬态;
该对象和任何session无关,在数据库中没有它的记录;
刚new出来的对象;
或已经删除的对象;
persistent:
持久对象的持久态;
该对象处于某session的管理中;
在数据库中有记录;
从数据库中取出的对象;
通过save()方法同步到数据库中的对象
detached:
游离态、脱管态;
当前和任何session无关,但在数据库中有记录;
session关闭后,就成了游离态了;
update()同步到数据库中;
持久化类与持久化对象是不同的概念,持久化类的实例可以处于临时状态,持久化
状态和游离状态,其中处于持久化状态的实例被称为持久化对象.
对象的状态有两种含义,一种含义是指由对象的属性表示的数据,一种含义是指临时状态,持久化状态或游离状态之一.应该根据上下文来辨别状态的具体含义.
get();
如果找到对象就返回,否则返回空;
load();
如果找到对象就返回,否则抛异常throwunrecoverableException;
s.close();
关闭session,对象变成游离的;
clear();
将session的缓冲区清空;
对象变成游离的对象;
内存中还有,但跟session已经无关了
evict(o1);
将一个对象清出去,变成游离状态
update(),saveOrUpdate();
使游离对象变成持久状态;
saveOrUpdate()方法同时包含了save与update方法的功能,如果传入的参数是临时对象,就调用save()方法,如果传入的参数是游离对象,就调用update()方法,如果传入的参数是持久化对象,就直接返回.那么,它是如何判断一个对象处于临时状态还是游离状态呢?
如果满足以下情况之一,Hibernate就把它当成临时对象:
1)Java对象的OID是null;
2)Java对象具有version属性并且取值为version
3)在映射文件中为id元素设置了unsaved-value属性,并且oid的取值与unsaved-value属性值匹配;
这种情况指的的是id属性是long类型,它的默认值是0,此时需要显式设置id元素的unsaved-value=&
0&
4)在映射文件为version属性设置了unsaved-value属性,并且version属性取值与unsaved-value属性值匹配;
delete()方法,用于从数据库中删除与java对象对应的记录.如果传入的参数是持久化对象,session就计划执行一个delete语句,如果传入的参数是游离对象,先使游离对象被session关联,使他变为持久化对象,然后计划执行一个delete语句,值得注意的是,session只有在清理缓存的时候才会执行delete语句.此外只有在调用session的close方法时,才会从session的缓存中删除该对象.
级联操作:
1、cascade
cascade属性是设置级联操作的.
也就是在操作一端的数据如果影响到多端数据时会进行级联操作,
none"
cascade="
delete"
persist"
delete-orphan"
cascade属性的值常用的设置为以上五项:
none就是不使用级联操作,默认级联是none。
save-update也就是只有对象保存操作(持久化操作)
或者是持久化对象的更新操作,才会级联操作关联对象(子对象)。
persist就只是将级联对象也持久化到数据库。
delete对持久化对象的删除操作时会进行级联操作关联对象(子对象)。
all对持久化对象的所有操作都会级联操作关联对象(子对象)。
包含save-update,和delete行为;
all-delete-orphan,从集合中删除时,同步将数据库中的记录删掉;
包含save-update,和delete-orphan行为;
delete之后将表中表示关联的外键id置成null,不会将这条纪录也删除掉;
delete-orphan就不会留有空纪录,而是级联的把相关纪录删除掉。
四、get、load的具体区别:
如果你使用load方法,hibernate认为该id对应的对象(数据库记录)在数据库中是一定存在的,所以它可以放心的使用,它可以放心的使用代理来延迟加载该对象。
在用到对象中的其他属性数据时才查询数据库,但是万一数据库中不存在该记录,那没办法,只能抛异常ObjectNotFoundException,所说的load方法抛异常是指在使用该对象的数据时,数据库中不存在该数据时抛异常,而不是在创建这个对象时。
由于session中的缓存对于hibernate来说是个相当廉价的资源,所以在load时会先查一下session缓存看看该id对应的对象是否存在,不存在则创建代理。
所以如果你知道该id在数据库中一定有对应记录存在就可以使用load方法来实现延迟加载。
对于get方法,hibernate会确认一下该id对应的数据是否存在,首先在session缓存中查找,然后在二级缓存中查找,还没有就查数据库,数据库中没有就返回null。
虽然好多书中都这么说:
get()永远只返回实体类&
,但实际上这是不正确的,get方法如果在session缓存中找到了该id对应的对象,如果刚好该对象前面是被代理过的,如被load方法使用过,或者被其他关联对象延迟加载过,那么返回的还是原先的代理对象,而不是实体类对象,如果该代理对象还没有加载实体数据(就是id以外的其他属性数据),那么它会查询二级缓存或者数据库来加载数据,但是返回的还是代理对象,只不过已经加载了实体数据。
前面已经讲了,get方法首先查询session缓存,没有的话查询二级缓存,最后查询数据库;
反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库。
总之对于get和load的根本区别,一句话,hibernate对于load方法认为该数据在数据库中一定存在,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,就抛异常;
而对于get方法,hibernate一定要获取到真实的数据,否则返回null。
五:
二级缓存:
在hibernate.cfg.xml中添加如下代码:
hibernate.cache.provider_class"
NHibernate.Caches.SysCache.SysCacheProvider,NHibernate.Caches.SysCache&
/property&
expiration"
120&
注意:
NHibernate.Caches.SysCache.SysCacheProvider,NHibernate.Caches.SysCache还可以替换为NHibernate.Caches.Prevalence.PrevalenceCacheProvider,NHibernate.Caches.Prevalence,代表缓存的实现类,在NHibernate的安装目录的bin目录中有这样两个dll:
N
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Hibernate 知识点小结 知识点 小结