在持久化层角度上说,一个java对象在生命周期中可以处于四个状态:
1. 临时状态(Transient):刚用new创建的对象,未被持久化,此时并没有处于Session缓存中
2. 持久化状态(Persistent):已经持久化,加入到了Session缓存中。
3. 游离状态(Detached):已经被持久化,但不再处于Session缓存中,此时数据库中依旧有记录
4. 删除状态(removed):不再处于Session缓存中,并且已经计划将其从数据库中删除。
下图是上述四种状态的描述:
缓存(Session/SessionFactoy)
Session 缓存是hibernate的第一级缓存,由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存,这一级缓存是必须的。
第二级缓存默认的情况下是打开的,由SessionFactoy管理,由于SessionFactory对象的生命周期和应用程序的整个进程对应,因此第二级缓存是进程范围或集群范围的缓存
SessionFactory对象的创建代价很昂贵,线程安全,它为所有的应用程序线程所共享。它只创建一次,通常是在应用程序启动的时候,由一个 Configuraion 的实例来创建。
一级缓存:
Session 对象的创建代价比较小,是非线程安全的,对于单个请求,单个会话、单个的 工作单元而言,它只被使用一次,然后就丢弃。只有在需要的时候,一个 Session 对象 才会获取一个 JDBC 的 Connection(或一个Datasource)对象,因此假若不使用的时候它不消费任何资源。
得到Session的方法有如下两个:
openSession :每次都是新的Session,并且要手动close
getCurrentSession:从上下文找,如已有那么用已经有的Session,如没有,创建新的;不需要手动close,当一个线程提交或撤销事务后hibernate自动关闭session对象;
<property name=”current_session_context_class”>thread</property>
current_session_context_class有四个值,两个是常用的:
thread:在线程里找是否有已经存在的Session(getCurrentSession());(最常用)
jta:主要针对数据库分布式而用;(处理多个数据库事务)
Transaction tx=session.beginTransaction(); //第一次执行get方法,先到Session 缓存中查找oid为1的User对象,由于不存在这样的对象,要向数据库查询, User u1=(User)session.get(User.class, new Long(1)); //第二次执行,由于在缓存中查找时能找到,故不再向数据库中执行sql语句 User u2=(User)session.get(User.class, new Long(1)); System.out.println(u2==u1);//true tx.commit();
二级缓存:
不是所有的数据都适合放在二级缓存中下面这几种情况就不适合加载到二级缓存中:
load、iterate默认使用二级缓存;
list默认往二级缓存加数据,但是查询的时候不使用,如果query用二级缓存,需打开查询缓存,只有查询条件一样时才会调用二级缓存
<property name="cache.use_query_cache">true</property> <!--查询缓存 -->
调用query的setCachable(true)方法指明使用二级缓存
如果配置了查询缓存,以下代码只发送一次sql请求:
public void testQueryCache() { Session session = sf.openSession(); session.beginTransaction(); List<Category> categories = (List<Category>)session.createQuery("from Category").setCacheable(true).list(); session.getTransaction().commit(); session.close(); Session session2 = sf.openSession(); session2.beginTransaction(); List<Category> categories2 = (List<Category>)session2.createQuery("from Category").setCacheable(true).list(); session2.getTransaction().commit(); session2.close(); }
EHCache的配置 hibernate.cfg.xml
<hibernate-configuration> <session-factory> <!-- 设置二级缓存插件EHCache的Provider类--> <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property> <!-- 启动"查询缓存" --> <property name="hibernate.cache.use_query_cache">true</property> </session-factory> </hibernate-configuration>
<ehcache> <!-- maxElementsInMemory为缓存对象的最大数目, eternal设置是否永远不过期,timeToIdleSeconds对象处于空闲状态的最多秒数,timeToLiveSeconds对象处于缓存状态的最多秒数 --> <diskStore path="java.io.tmpdir"/> <defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600" overflowToDisk="true"/> </ehcache>****.hbm.xml
<hibernate-mapping> <class> <!-- 设置该持久化类的二级缓存并发访问策略 read-only read-write nonstrict-read-write transactional--> <cache usage="read-write"/> </class> </hibernate-mapping>
二级缓存也可以用annotation配置:http://docs.jboss.org/hibernate/annotations/3.4/reference/zh_cn/html_single/
缓存算法有: