hibernate杂记
1、hibernate中get和load方法有什么不同?
(1)执行get方法,会立即加载对象, 执行load方法,若不使用该对象,则不会立即执行查询操作。 (2)load 方法可能会抛出 LazyInitializationException 异常: 在需要初始化 代理对象之前已经关闭了 Session (3)若数据表中没有对应的记录, Session 也没有被关闭. get 返回 null load 若不使用该对象的任何属性, 没问题; 若需要初始化了, 抛出异常.
2、增删查改?
3、数据库的隔离级别?
I. 对于同时运行多个事务,当这些事务访问数据库中的相同数据时,如果没有采取必要的隔离机制,就会导致各种并发问题。
(1)脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.
(2)不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了.
(3)幻读: 对于两个事物 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行.
II.数据库事务的隔离性:数据库必须的隔离并发运行多个事务的能力,使它们不会相互影响,避免各种并发问题。
III.隔离级别:一个事务与其它事务的隔离程度称为隔离级别,数据库规定了多种隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数扰一致性就越好,但并发性也就越弱。
(1)读未提交数据,允许事务读取未被其它事务提交的变更,上面三个问题都会出现。
(2)读已提交数据,允许事务读取被其它事务提交的变理,避免脏读,但会出现不可重复读和幻读。
(3)可重复读,确保一个事务可以从一个字段读取相同的值,在此事务持续期间,禁止其它事务操作该字段,幻读问题仍存在
(4)串行化,效率低
IV.mysql默认的隔离级别是可重复读,设置数据库隔离级别有两种方式
(1)使用Sql语句修改数据库的隔离级别。
(2)在 Hibernate 中设置隔离级别
READ UNCOMMITED
READ COMMITED
REPEATABLE READ
SERIALIZEABLE
4、hibernate中对象的四种状态?
(1)临时状态
新new出一个对象OID 通常为 null,不存在于Session缓存中,也不存在于数据库中
(2)持久化状态
临时状态对象通过Session的save()方法和saveOrUpdate()方法可以把一个临时对象和数据库相关联,并把临时对象携带的信息通过配置文件所做的映射插入数据库中,这个临时对象就成为持久化对象。
持久化对象在数据库中有相应的记录,持久化对象可以是刚被保存的,或者刚被加载的,但都是在相关联的session声明周期中保存这个状态。
(3)脱管状态
Session关闭之后,与此Session关联的持久化对象就变成为脱管对象,
OID 不为 null
不再处于 Session 缓存中
般情况需下, 游离对象是由持久化对象转变过来的, 因此在数据库中可能还存在与它对应的记录
5、hibernate一级缓存和二级缓存的比较?
(1)一级缓存,是Session级别的缓存
hibernate的session接口实现中,包含一系列的java集合,这些java集合构成了session缓存,只要 Session 实例没有结束生命周期, 且没有清理缓存,则存放在它缓存中的对象也不会结束生命周期。
Session 缓存可减少 Hibernate 应用程序访问数据库的频率。
它是属于事务范围的缓存。这一级别的缓存由 hibernate 管理的
(2)二级缓存,是SessionFactory级别的缓存
二级缓存分为两类:
I.内置缓存: Hibernate 自带的, 不可卸载. 通常在 Hibernate 的初始化阶段, Hibernate 会把映射元数据和预定义的 SQL 语句放到 SessionFactory 的缓存中, 映射元数据是映射文件中数据
(.hbm.xml 文件中的数据)的复制. 该内置缓存是只读的.
II.外置缓存(二级缓存): 一个可配置的缓存插件. 在默认情况下, SessionFactory 不会启用这个缓存插件. 外置缓存中的数据是数据库数据的复制, 外置缓存的物理介质可以是内存或硬盘
二级缓存的配置方式
I.配置文件
<ehcache>
<!--
指定一个目录:当 EHCache 把数据写到硬盘上时, 将把数据写到这个目录下.
-->
<diskStore path="d:\\tempDirectory"/>
<!--
设置缓存的默认数据过期策略
-->
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<!--
设定具体的命名缓存的数据过期策略。每个命名缓存代表一个缓存区域
缓存区域(region):一个具有名称的缓存块,可以给每一个缓存块设置不同的缓存策略。
如果没有设置任何的缓存区域,则所有被缓存的对象,都将使用默认的缓存策略。即:<defaultCache.../>
Hibernate 在不同的缓存区域保存不同的类/集合。
对于类而言,区域的名称是类名。如:com.atguigu.domain.Customer
对于集合而言,区域的名称是类名加属性名。如com.atguigu.domain.Customer.orders
-->
<!--
name: 设置缓存的名字,它的取值为类的全限定名或类的集合的名字
maxElementsInMemory: 设置基于内存的缓存中可存放的对象最大数目
eternal: 设置对象是否为永久的, true表示永不过期,
此时将忽略timeToIdleSeconds 和 timeToLiveSeconds属性; 默认值是false
timeToIdleSeconds:设置对象空闲最长时间,以秒为单位, 超过这个时间,对象过期。
当对象过期时,EHCache会把它从缓存中清除。如果此值为0,表示对象可以无限期地处于空闲状态。
timeToLiveSeconds:设置对象生存最长时间,超过这个时间,对象过期。
如果此值为0,表示对象可以无限期地存在于缓存中. 该属性值必须大于或等于 timeToIdleSeconds 属性值
overflowToDisk:设置基于内存的缓存中的对象数目达到上限后,是否把溢出的对象写到基于硬盘的缓存中
-->
<cache name="com.atguigu.hibernate.entities.Employee"
maxElementsInMemory="1"
eternal="false"
timeToIdleSeconds="300"
timeToLiveSeconds="600"
overflowToDisk="true"
/>
<cache name="com.atguigu.hibernate.entities.Department.emps"
maxElementsInMemory="1000"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
</ehcache>
II.引入jar包
复制 \hibernate-release-4.2.4.Final\lib\optional\ehcache\*.jar 到当前 Hibrenate 应用的类路径下.
复制 hibernate-release-4.2.4.Final\project\etc\ehcachexml 到当前 WEB 应用的类路径下
III.配置hibernate使用二级缓存
配置启用 hibernate 的二级缓存
<property name="cache.use_second_level_cache">true</property>
IV.配置二级缓存使用的产品
配置hibernate二级缓存使用的产品
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
V.配置哪些类使用二级缓存
<class-cache usage="read-write" class="com.atguigu.hibernate.entities.Employee"/>
6、hibernate的延迟加载机制
延迟加载(lazy load)也叫懒加载,它是Hibernate为提高程序执行效率而提供的一种机制,即只有真正使用该对象的数据时才会创建。
Hibernate中主要通过代理(proxy)机制来实现延迟加载的。具体过程:Hibernate从数据库获取某一个对象数据时、获取某一个对象的集合属性值时,或获取某一个对象所关联的另一对象时,由于没有使用该对象的数据(除标识符值外),Hibernate并不从数据库加载真正的数据,而只是为该对象创建一个代理对象来代表这个对象,这个对象上的所有属性都为默认值;只有在真正需要使用该对象的数据时才创建这个真实对象,真正从数据库中加载它的数据
Hibernate中默认采用延迟加载的情况主要由以下几种:
(1)当调用Session上的load()方法加载一个实体时,会采用延迟加载。
(2)当Session加载某个实体时,会对这个实体中的集合属性值采用延迟加载。
(3)当Session加载某个实体时,会对这个实体所单端关联的另一个实体对象采用延迟加载。