**JAVA Hibernate工作原理及为什么要用:
hibernate 简介:(orm object relation mapping)
hibernate是一个开源框架,它是对象关联关系映射的框架,它对JDBC做了轻量级的封装,而我们Java程序员可以使用面向对象的思想来操纵数据库。
hibernate核心接口
session:负责被持久化对象CRUD操作
sessionFactory:负责初始化hibernate,创建session对象
configuration:负责配置并启动hibernate,创建SessionFactory
Transaction:负责事物相关的操作
Query和Criteria接口:负责执行各种数据库查询
hibernate工作原理:
1.通过Configuration config = new Configuration().configure();//读取并解析hibernate.cfg.xml配置文件
2.由hibernate.cfg.xml中的<mapping resource="com/xx/User.hbm.xml"/>读取并解析映射信息
3.通过SessionFactory sf = config.buildSessionFactory();//创建SessionFactory
4.Session session = sf.openSession();//打开Sesssion
5.Transaction tx = session.beginTransaction();//创建并启动事务Transation
6.persistent operate操作数据,持久化操作
7.tx.commit();//提交事务
8.关闭Session
9.关闭SesstionFactory
为什么要用hibernate:
1. 对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。
2. Hibernate是一个基于JDBC的主流持久化框架,是一个优秀的ORM实现。他很大程度的简化DAO层的编码工作
3. hibernate使用Java反射机制,而不是字节码增强程序来实现透明性。
4. hibernate的性能非常好,因为它是个轻量级框架。映射的灵活性很出色。它支持各种关系数据库,从一对一到多对多的各种复杂关系。
一、对Hebernate缓存的理解:
hibernate的缓存目前比较常见的使用是它的:一级缓存(Session缓存),二级缓存(第三方插件缓存)。
缓存:
缓存就是把当前查询出来或是使用过的对象保存到内存中(一个数据结构当中),这个数据结构通常是或类似于hashMap,当以后要使用某个对象时, 会先到缓存中去找有没有这个对象,如果有就使用缓存中的,如果没有就 到数据中去查询,并将查询出来的数据保存到缓存中,方便下次使用。即使用缓存会涉及到三个方面:把数据放入缓存,从缓存中读取缓存,删除无用的缓存。
一级缓存:
Hibernate的session是一种缓存,通常被称为hibernate的一级缓存。用session查询数据时,首先会从session内部去找有没有,有就使用session中的,没有就到数据库中去查,并将查到的结果放到session中,方便下次使用。由于session代表一次会话,与一个数据库连接相关联,所以session最好不要长时间保持打开,通常仅用于一个事务当中,事务关闭的时候就应该结束。另外,session是线程不安全的,当多线程共享使用时会出现问题。通常只有那种全局意义的缓存才是真正的缓存应用,才有大的缓存使用价值。二级缓存就能达到这个使用价值。Session级共享的: save, update, saveorupdate, list, get, load, iterate, lock这些方法都会放在一级缓存中。Session缓存的另一个缺点是不能控制缓存的数量,当大批量数据操作时会造成数据的溢出。但可以用evict, clear去清除缓存。
二级缓存:
它是独立于hibernate的一个软件部件,属于第三方产品,常用的第三方缓存产品有:EhCache, OsCache, TreeCache,SwarmCache。可以通过对org.hibernate.cache.EhCacheProvider和Cache接口来实现。二级缓存的配置: 首先,开启缓存,确定使用哪个产家的第三方产品,配置该缓存自己的配置文件,然后要配置hibernate中那些对象需要纳入二级缓存中,这就是这的配置思路。另处需要注意的是,一个二级缓存只能负责缓存一个数据库中的数据,否则就会造成与实际数据不相符。
二、get 和 load 的区别:
1.get()采用立即加载方式,而load()采用延迟加载;
get()方法执行的时候,会立即向数据库发出查询语句,
而load()方法返回的是一个代理(此代理中只有一个id属性),只有等真正使用该对象属性的时候,才会发出sql语句
2.如果数据库中没有对应的记录,get()方法返回的是null.而load()方法出现异常ObjectNotFoundException
三、hibernate中的session.flush()和commit()的区别:
1、flush()方法进行清理缓存的操作,执行一系列的SQL语句,但不会提交事务;commit()方法会先调用flush()方法,然后提交事务. 提交事务意味着对数据库所做的更新会永久保持下来 所谓清理,是指hibernate 按照持久化象的状态来同步更新数据库
2、Flush()后只是将Hibernate缓存中的数据提交到数据库,如果这时数据库处在一个事物当中,则数据库将这些SQL语句缓存起来,当Hibernate进行commit时,会告诉数据库,你可以真正提交了,这时数据才会永久保存下来,也就是被持久化了.
3、commit针对事物的,flush针对缓存的, 数据同步到数据库中后只要没有commit还是可以rollback的。
可以这么理解,hibiernate有二级缓存,而平时一般只用一级缓存(默认开启),也就是session级的缓存。处于一个事务当中,当save的时候,只是把相应的insert行为登记在了以及缓存上,而flush是把缓存清空,同时把insert行为登记在数据库的事务上。当commit提交之后,才会执行相应的insert代码,而commit又是隐性的调用flush的,那在commit之前调用flush的作用的什么?我的理解是防止多条SQL语句冲突,这是因为flush到数据库中执行SQL语句的顺序不是按照你代码的先后顺序,而是按照insert,update....delete的顺序执行的,如果你不按照这个顺序在代码中编写,如果逻辑一旦出错就会抛exception了,解决这个的办法之一就是在可能其冲突的SQL操作后面flush一下,防止后面的语句其冲突
同时flush的作用,也有提交大量数据时候清理缓存的作用
***flush()操作的是Hibernate的缓存,将Hibernate中缓存的数据提交到DB层,如果这时候DB处于事物当中,那是DB的事情,与Hibernate无关了,commit()是告诉DB我这个事物结束了,你可以将我刚刚提交给你的数据进行更新.
四、Hibernate持久化对象的三个状态:
hibernate中的对象有3中状态,瞬时对象(TransientObjects)、持久化对象(PersistentObjects)和离线对象(DetachedObjects也叫做脱管对象)。