`

Hibernate的clear(),flush(),evict()方法详解

 
阅读更多

1.Clear 方法

      无论是Load 还是 Get 都会首先查找缓存(一级缓存) 如果没有,才会去数据库查找,调用Clear() 方法,可以强制清除Session缓存。

例:

 

[c-sharp] view plaincopyprint?
 
  1. public void testClear(){  
  2.         Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  
  3.         session.beginTransaction();  
  4.         Teacher t = (Teacher) session.get(Teacher.class, 3);  
  5.         System.out.println(t.getName()); 
  6.         Teacher t2 = (Teacher) session.get(Teacher.class, 3);  
  7.         System.out.println(t2.getName());  
  8.         session.getTransaction().commit();  
  9.     }  

 

 

这里虽然用了2  get 方法( get 方法会立即执行 sql 语句),但因为第一次执行了会缓存一个 ID  3 的实体,所以虽然有 2  get 方法只执行一次 SQL 语句。

 

 

[c-sharp] view plaincopyprint?
 
  1. public void testClear(){  
  2.         Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  
  3.         session.beginTransaction();  
  4.         Teacher t = (Teacher) session.get(Teacher.class, 3);  
  5.         System.out.println(t.getName());  
  6.         session.clear();//这里不clear只会执行一次sql语句,有clear会执行2次  
  7.         Teacher t2 = (Teacher) session.get(Teacher.class, 3);  
  8.         System.out.println(t2.getName());  
  9.         session.getTransaction().commit();  
  10.     }  

 

 

这里在第2  get 前执行 session.clear(), 我们把 hibernate show_sql  出来,它就会执行 2  sql 语句了。 所以session.clear() 会清除缓存。

 

2.Flush方法

      可以强制进行从内存到数据库的同步。

例:

 

  1. @Test  
  2.     /** 
  3.      * flush 强制与数据库同步 
  4.      */  
  5.     public void testFlush(){  
  6.         Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  
  7.         session.beginTransaction();  
  8.         Teacher t = (Teacher) session.get(Teacher.class, 3);  
  9.         t.setName("yyy");  
  10.    
  11.         t.setName("yyyyy");  
  12.         session.getTransaction().commit();  
  13.     }  

 

 

看这段代码,我们setName() 2 次, 但程序只会更改数据库一次,在 commit 时。

 

 

  1. @Test  
  2.     /** 
  3.      * flush 强制与数据库同步 
  4.      */  
  5.     public void testFlush(){  
  6.         Session session =  HibernateUitl.getSessionFactory().getCurrentSession();  
  7.         session.beginTransaction();  
  8.         Teacher t = (Teacher) session.get(Teacher.class, 3);  
  9.         t.setName("yyy");  
  10.         session.flush();//有flush会执行2次UPDAE,没有会只执行一次  
  11.         t.setName("yyyyy");  
  12.         session.getTransaction().commit();  
  13.     }  

 

 

我们在第2  setName ()时 执行 session.flush().

 

再看hibernate  执行的 sql  语句

 

  1. Hibernate:   
  2.     update  
  3.         Teacher   
  4.     set  
  5.         birthday=?,  
  6.         name=?,  
  7.         title=?   
  8.     where  
  9.         id=?  
  10. Hibernate:   
  11.     update  
  12.         Teacher   
  13.     set  
  14.         birthday=?,  
  15.         name=?,  
  16.         title=?   
  17.     where  
  18.         id=?  

 

 

执行了2  Update

 

所以看出来flush 方法会强制与数据库同步。

 

 

 

 

Flush方法是可以设置的,也就是 fulsh 什么时候执行是可以设置的

 

 在session.beginTransaction 前设置 FlushMode

 

session.setFlushMode(FlushMode.Always|AUTO|COMMIT|NEVER|MANUAL)

 

FlushMode 5 个值可选

Always:任何代码都会 Flush 
AUTO:默认方式  自动 
Commit:COMMIT 
Never:始终不 
MANUAL:手动方式

 

设置FlushMode  有个好处是可以节省开销,比如默认 session 只做查询时,就可以不让他与数据库同步了。

 

 

session.evict(obj) :会把指定的缓冲对象进行清除。 

  session.clear() :把缓冲区内的全部对象清除,但不包括操作中的对象。 

  Hibernate 执行的顺序如下: 
 (1) 生成一个事务的对象,并标记当前的 Session 处于事务状态(注:此时并未启动数据库级事务)。 
 (2) 应用使用 s.save 保存对象,这个时候 Session 将这个对象放入 entityEntries ,用来标记对象已经和当前的会话建立了关联,由于应用对对象做了保存的操作,Session 还要在 insertions 中登记应用的这个插入行为(行为包括:对象引用、对象 id  Session 、持久化处理类)。 
 (3)s.evict 将对象从 s 会话中拆离,这时 s 会从 entityEntries 中将这个对象移出。 
 (4) 事务提交,需要将所有缓存 flush 入数据库, Session 启动一个事务,并按照 insert,update,……,delete 的顺序提交所有之前登记的操作(注意:所有 insert 执行完毕后才会执行 update ,这里的特殊处理也可能会将你的程序搞得一团糟,如需要控制操作的执行顺序,要善于使用 flush ),现在对象不在 entityEntries 中,但在执行 insert的行为时只需要访问 insertions 就足够了,所以此时不会有任何的异常。异常出现在插入后通知 Session 该对象已经插入完毕这个步骤上,这个步骤中需要将entityEntries 中对象的 existsInDatabase 标志置为 true ,由于对象并不存在于 entityEntries 中,此时 Hibernate 就认为 insertions  entityEntries 可能因为线程安全的问题产生了不同步(也不知道 Hibernate 的开发者是否考虑到例子中的处理方式,如果没有的话,这也许算是一个 bug 吧),于是一个 net.sf.hibernate.AssertionFailure 就被抛出,程序终止。 

         一般我们会错误的认为 s.save 会立即执行,而将对象过早的与 Session 拆离,造成了 Session  insertions  entityEntries 中内容的不同步。所以我们在做此类操作时一定要清楚 Hibernate 什么时候会将数据 flush 入数据库,在未 flush 之前不要将已进行操作的对象从 Session 上拆离。解决办法是在 save 之后,添加 session.flush  

分享到:
评论

相关推荐

    详解Hibernate的缓存机制及其配置代码

    ### 详解Hibernate的缓存机制及其配置代码 #### 一、缓存概念及目的 缓存作为一种优化技术,在软件开发中扮演着极其重要的角色。它位于应用程序与物理数据源(如数据库)之间,用于临时存储数据的副本,旨在减少...

    Hibernate 使用缓存时,数据同步问题

    4. **清除缓存**:在必要的时候,可以显式地调用`Session.clear()`方法清除一级缓存,或者使用`SessionFactory.evict()`方法清除二级缓存中的特定实体,以确保下一次操作时能获取到最新的数据。 5. **配置缓存模式*...

    Hibernate性能优化策略.

    ### Hibernate性能优化策略详解 #### 一、并发控制机制——乐观锁与悲观锁 在并发环境中,为了确保数据的一致性和完整性,Hibernate 提供了两种并发控制机制:乐观锁(Optimistic Locking)和悲观锁(Pessimistic ...

    Hibernate 缓存

    【Hibernate 缓存详解】 在Java的ORM框架Hibernate中,缓存机制是提高应用程序性能的重要手段。Hibernate提供了两级缓存,分别是:一级缓存和二级缓存,以及一种特殊的QueryCache。 1. 一级缓存(Session级缓存) ...

    Hibernate缓存

    ### Hibernate缓存详解 在深入理解Hibernate框架的过程中,缓存机制是至关重要的组成部分之一。本文将详细介绍Hibernate中的一级缓存和二级缓存,并提供具体的配置示例。 #### 一、一级缓存(Session Cache) 一...

    hibernate 学习笔记3

    - **持久态 ↔️ 游离态**:可通过`session.evict()`、`session.close()`或`session.clear()`等方法使对象进入游离态。 - **游离态 → 持久态**:使用`session.update()`或`session.saveOrUpdate`方法将游离态对象...

    Hibernate_学习笔记.

    ### Hibernate学习笔记知识点详解 #### Hibernate简介 - **定义**:Hibernate是一种开源的对象关系映射(ORM)框架,用于在Java应用中简化数据库操作。 - **创始人**:由Gavin King于2001年创建。 - **作用**:提供...

    jsp Hibernate 函数简介

    #### 二、Session 的常用方法详解 - **save()**:该方法将对象保存到数据库中,相当于执行 `INSERT` SQL 语句。 - **persist()**:此方法与 `save()` 功能类似,都用于将对象持久化到数据库。但 `persist()` 提供...

Global site tag (gtag.js) - Google Analytics