hibernate总结
hibernate
Hibernate是什么?
hibernate是一个开源的对象关系映射框架,对jdbc进行了非常轻量级的封装,使程序员可以使用对象的思维来操作数据库
Hibernate的三种状态?
持久态:持久态就是该数据对象在数据可中有关系,
脱管态:脱管态就是当该持久对象关联的session对象关闭了就是脱管态。
瞬时态:当一个session执行close()或clear()、evict()之后,持久对象变成脱管对象,此时持久对象会变成脱管对象,
此时该对象虽然具有数据库识别值,但它已不在HIbernate持久层的管理之下。
hibernate的缓存机制?
缓存是位于应用程序和物理数据之间,用于临时存放复制数据的内存区域,hibernate的缓存是有级别的分别分为一级缓存和二级缓存
一级缓存:session
其实就是Session内置的一个Map,用来缓存它操作过的实体对象,对象的主关键字ID是Map的key,实体对象就是对应的值
二级缓存是sessionFactory
内置缓存
内置缓存里sessionFactory的一个map集合
外置缓存
外置缓存放的是数据库数据的副本,ehcache是二级缓存中外部缓存的插件
适合放在二级缓存中的数据
(1)经常被访问
(2)改动不大
(3)数量有限
(4)不是很重要的数据,允许出现偶尔并发的数据。
hibernate缓存范围
事务范围
事务范围的缓存只能被当前事务访问,缓存内采用数据相互关联,缓存的生命周期和事务的生命周期一样事务开始缓存的生命开事务提交缓存的生命结束
应用范围
应用范围是缓存的范围是应用的所有程序的事务共同访问,这里缓存的生命周期和应用的生命周期是一样
集群范围
集群范围,在集群环境中,缓存被一个机器或多个机器的进程共享,缓存中的数据被复制到集群环境中的每个进
程节点,进程间通过远程通信来保证缓存中的数据的一致,缓存中的数据通常采用对象的松散数据形式
hibernate中的六大接口
session
负责保存、更新、删除、加载和查询对象
Configuration
配置Hibernate,根启动Hibernate,创建SessionFactory对象。
sessionFactory
初始化Hibernate,充当数据存储源的代理,创建Session对象
Transaction
管理事务
query
执行数据库查询。
Criteria
执行数据库查询。
hibernate和ibatis的去区别
第一点:hibernate可以使程序员以对象的思维来操作数据库ibatis是
第二点:hibernate是全自动化的ibatis是半自动化的为什么说hibernate是全自动化的呢?因为使用
hibernate可以不用自己写sql语句,ibatis是半自动的是要自己写sql返回的时候只要自己定义一个返回类型就可以了。
第三点:hibernate的是直接用orm也就是bean里的字段和hibernate.chb.xml中字段对应和数据库里的字段相互匹配直接在
dao里进行操作,ibatis也是通过orm来映射的但是它是要自己写sql把sql语句提取到了一个xml文件里在dao里调用xml里的sql语句。
第四点:hibernate的查询方式有好多种列(hql,bql,sql等等),ibatis的查询方式可以说就一种原生态sql查询,第五点:hibernate的流程主要是通
过Configuration来创建sessionFactory,打开session,开始事物执行持久层代码,提交事务,关闭session,关闭sessionFactory。ibatis是不需要通过来session来操作的。
第五点:hibernate是ORM对ibatis来说ibatis是一种sqlMappingdeORM实现
hibernate的优点
1:hibernate不需要自己写sql语句,
2:在做大型项目的开发用hibernate计较好可以大大提交开发效率因为不需要自己写sql,比如用ibatis和hibernate同时修改一个表字段hibernate只要修改bean类和hibernate.chb.xml文件ibatis要修改bean和写了sql语句的xml里有用到这个字段都要修改。
3:hibernate可以随便切换数据库ibatis不可以因为hibernate有数据库方言。
hibernate的缺点
当系统数据量超大,性能要求极为苛刻,我们必须对sql语句进行高度优化才能达到系统性能指标,在这个情况下我们有ibatis计较好,ibatis可以进行细粒度的优化比如说用ibatis修改表里的一个字段直接把那个字段拿出开进行修改其它字段不受影响,在hibernate里修改表里的一个字段其它字段会修改成null的。
hibernate中get和load的区别
load方法检索不到的话会出org.hibernate.ObjectNotFoundException异常,
get方法检索不到的话会出会抛出null异常,
get和load都是要同过id来检索的get方法每次都都直接从数据库里查询出来的,load方法如何检索到id存在那它就会通过ognl代理,首先是把id查询出来在你用到这条sql是它就会再次去数据库里把这条sql查询出来这就是延迟加载。get方法首先查询session缓存,没有的话查询二级缓存,最后查询数据库;反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存或数据库。
hibernate的常用术
Po(persistantobject)持久化对象Po中应该不包含任何对数据库的操作
PoJo(plainordinaryjavaobject)简单无规则java对象最基础的javabean类,里面只有属性字段以及get、set方法
Vo(valueobject)值对象业务层之间的数据传递,和PO一样也是仅仅包含数据而已
Bo(businessobject)业务对象通过调用数据访问对象中的方法,结合持久化对象和值对象对数据库进行业务处理
Dao(dataaccessobject)数据访问对象
DAO中包含了各种数据库的操作方法,通常和持久化对象结合使用,通过它的方法,结合持久化对象对数据库进行相关的操作
dto(DataTransferObject)数据传输对象主要用于远程调用等需要大量传输对象的地方。
hibernate中list和iterator
共同点每次发送sql语句返回来的结果是一模一样的
在一般情况下list是不会利用缓存的iterator会利用缓存
当hibernate的二级缓存开启的时候由session对象来得到的如何对象hibernate都会把它放到缓存中知道该对象被修改或者删除或是直接从缓存中删除,list查询数据放到缓存中如果sql不变的情况下list第二次查询是不会到数据库里查询直接从缓存中查询,iterator也是一样的
hibernate的查询方式
Hql查询是在from后面把表名换成类名在添加条件查询时字段写bean类里的字段。
Qbc查询使用hibernate提供的QueryByCriteriaAPI来查询对象,这种API封装了SQL语句的动态拼装。
sql查询方式是直接写sql语句就是写原生态的sql
ibernate修改的几种常用方法
saveorupdate
saveorupdate是对数据的保存或是修改当你传进来的id它是在
数据库里有的它就会进行对这条数据进行修改当你传进来的id是在数据库里不存在的它会把这条数据新增加到数据库里(注意!在这里如果你的id是自动增长的那你要进行一些判断如果你要修改的id不存在这时候他就会抛出异常)
update
update是直接进行修改当你传进来的id不存在数据库里就会抛出异常存在就修改。
merge
merge在这里不管你的id是自动增长的还是你自己输入的你传进来的id存在就修改不存在就进行保存
锁
悲观锁
在处理数据中将数据处于锁定状态说通俗一点你在操作数据的时把数据封死了,其他人只能读不能写
悲观锁是依靠数据库里的锁机制来实现的,在你执行的语句后加一个forupdate就锁死了外界无法修改这些记录
乐观锁
大多是基于数据版本(Version)记录机制实现
乐观锁的工作原理:读取出数据时,将此版本号一同读出,之后更新时,对此版本号加一。此时,将提交数据的版本数据与数据库表对应记录的当前版本信息进行比对,如果提交的数据版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。
隔离级别与并发性能的关系
事务的隔离级别越高并发性越低
(序列化)serializable的隔离级别最高并发性也是最低的
(重复读)repeatableread的隔离级别第二高并发性也是第二低的
(提交读)readcommitted的隔离级别第三高并发性也是第三低的
(未提交读)readuncommitted的隔离级别最低并发性也是最高的
hibernate的性能优化
1,尽量减少程序与数据库的交互次数。也就是使用缓存能够减少交换次数。
2,在使用hibernate处理大数据时候,可以使用session.clear()或者session.evict()清空所用缓存和
清除某个对象
3,在编写代码的时候请,对将POJO的getter/setter方法设定为public,如果设定为private,
Hibernate将无法对属性的存取进行优化,只能转而采用传统的反射机制进行操作,这将导致大。
4,对大数据量查询时,慎用list()或者iterator()返回查询结果。使用scroll()可以得到较好的处理速
度以及性能。而且直接对结果集向前向后滚动。
5,Hibernate可以通过设置hibernate.jdbc.fetch_size和hibernate.jdbc.batch_size等属性,
对Hibernate进行优化。
6,采用延迟加载,可以提高性能
a,session的load()方法对实体的加载默认采用延迟加载,而get()方法默认采用立即加载。
b,在单项关联配置一对多、多对一的关系中,lazy默认为true,
如果lazy=false,使用延迟加载机制,减少数据的负担,需要用到时才加载。
c,在映射文件在的集合,<bag>,<list>,<set>设置为延迟加载,也就是lazy=false。
7,解决n+1问题
单端关联(<one-to-one>、<many-to-one>)上的抓取策略
a,select:作为默认值,它的策略是当需要使用到关联对象的数据时,另外单独发送一条select语句
抓取当前对象的关联对象的数据,也就是会发送n+1条sql进行查询
b,join:采用的是左右连接的方式进行查询数据,可以解决了n+1问题,提高性能
采用cqb查询语句
8,在one-to-many关系中,将many一方设为主动方(inverse=false)将有助性能的改善。
9,在级联关系中将cascade="all/save-update"的时候注意赋值操作,容易多执行一次update操作
10,主键生成机制不要使用数据库最大值+1的自增长,减少了一次select语句。
推荐使用uuid.hex作为主键生成机制
11:对大数据量查询的时候尽量使用iterator避免使用list因为使用list查询结果集较大时会占用较大的处理时间,用iterator.next,结果集较大时使用iterator()才有优势。
12:在one-to-many关系中,将many一方设为主动方(inverse=false)将有助性能的改善。
hibernate的抓取策略
连接抓取
fetch="joio"
Hibernate通过在SELECT语句使用OUTERJOIN
查询抓取
fetch="select"
另外发送一条SELECT语句抓取当前对象的关联实体或集合。除非你显式的指定lazy="false"禁止延迟抓取(lazyfetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句.