`
holdbelief
  • 浏览: 707715 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Hibernate2.0中,关于session.flush()的理解

 
阅读更多

Hibernate2.0中,关于session.flush()的理解

    刚刚开始时,阅读孙维琴的《精通 Hibernate:Java 对象持久化技术详解.pdf》一书,由于不仔细误解了书中的意思,书中的意思是当程序显式调用session.flush()方法时,session会清理 缓存,而我却误解为清空 缓存。差之毫厘,谬之千里...

    清理是什么意思呢?一下是《精通 Hibernate:Java 对象持久化技术详解.pdf》的说法:

     当Session加载了一个PO对象,会为这个PO对象的值类型的属性复制一份快照,当Session清理缓存时,通过比较PO对象的当前属性与它的快照,Session能够判断PO对象的哪些属性发生了变化。

    就是说,清理的意思就是让PO对象的快照与PO对象同步。

    在网上查了一下,关于session.flush()对这个方法有的误解的人还不止我一个,误解的地方也各不相同,所以想先做些关于这个方法的实验,然后把结果写出来,大家一起探讨阿,呵呵。

    引用一下《精通 Hibernate:Java 对象持久化技术详解.pdf》中的原话吧:

    注意Session的commit()和flush()方法的区别。flush()方法进行清理缓存的操作,执行一系列的SQL语句,但不会提交事务;commit()方法会先调用flush()方法,然后提交事务。提交事务意味着对数据库所做的更新被永久保存下来。

    先建一个简单的Hibernate项目,数据库只有一个表:很简单,就为做session.flush()的实验,没有任何实际的业务逻辑。

 

 

DAO的代码如下:

L01-package com.dao;

L02-import org.hibernate.Session;
L03-import org.hibernate.Transaction;

L04-import com.HibernateSessionFactory;
L05-import com.po.User1;

L06-public class User1DAO {

L07- Session se = HibernateSessionFactory.getSession();
L08- User1 user =null;

L09- public void modifyUser() throws Exception
L10- {
L11-     Transaction tx = null;

L12-     tx = se.beginTransaction();
L13-     user = (User1)se.get(User1.class, "id1");
L14-     user.setName("name1_2");

L15-     se.flush();
L16-     System.out.println(user.getName());//在这一行设置断点

L17-     tx.commit();
L18-     System.out.println(user.getName());

L19-     se.close();
L20- }

L21- public static void main(String[] args) throws Exception {
L22-     User1DAO user1DAO = new User1DAO();
L23-     user1DAO.modifyUser();
L24- }
L25-}

    在第16行设置断点,当程序运行到断点时,我们看看se.flush()这个方法做了些什么,程序不要往下运行,让程序在断点处保持挂起,打开数据库的企业管理器(SQL SERVER2000),出现下面的情况:

    数据库连接超时,这说明什么??如果把企业管理器也看作一个事务,那么就是有另一个事务锁住了数据库,导致企业管理器这个事务无法看到数据,另一个事务是谁呢,就是session.flush() 它了。那么session.flush()的作用就是让数据库执行SQL语句,但是不提交。所以只要程序一直在断点处挂起,其他的事务就不能看到数据。即便是使用企业管理企业也不行。

    但是为什么要这样呢??没有事务会引起的问题之一就是脏读——A事务读取了B事务尚未提交的更改数据,并在这个数据的基础上操作。所以如果假如企业管理器能让你看到数据,那看到的就是脏数据,SQL Server当然不允许这样的事情发生。

    另外还有两点说明:

    1. 在程序的第14行, user.setName("name1_2");使用setter方法对user的name属性赋了新值,假如没有赋值

  • a.没有调用setName(String)方法。
  • b.调用了setName(String)方法,但是参数与原来数据库中的值相同(都是"name1_1")

两种方式的结果是相同的,Hibernate都不会生成update的sql语句,也都不会锁数据库,大家可以试一下。
    2.是什么级别的锁呢?
    这个通过企业管理器貌似看不出来,打开查询分析器看看。
    select * from dbo.User1;                 --对整个表的查询
    select * from dbo.User1 where id='id1';  --对正在修改的那一行的查询
    select * from dbo.User1 where id='id2';  --对其他行的查询
在查询分析器里,第一二句sql都因为记录被锁而无法查出数据,只有第三行记录可以查出数据。
    所以结论是当程序执行se.flush()时,数据库上的锁是行级别的独占锁。
                                                                                             
还没完,企业管理其不能看,那么理论上另一个Session也不能得到数据,试试看:
L01- package com.dao;

L02- import org.hibernate.Session;
L03- import org.hibernate.Transaction;

L04- import com.HibernateSessionFactory;
L05- import com.po.User1;

L06- public class User1DAO {

L07- Session se = HibernateSessionFactory.getSession();
L08- Session se2 = HibernateSessionFactory.getSession2();
L09- User1 user =null;

L10- public void modifyUser() throws Exception
L11- {
L12-     Transaction tx = null;

L13-     tx = se.beginTransaction();
L14-     user = (User1)se.get(User1.class, "id1");
L15-     user.setName("name1_1");

L16-     se.flush();
L17-     //tx.commit();
L18-     //se.close();
L19- }

L20- public void modifyUser2() throws Exception
L21- {
L22-     Transaction tx = null;
L23-     tx = se2.beginTransaction();
L24-     user = (User1)se2.get(User1.class, "id1");
L25-     System.out.println(user.getName());
L26-     tx.commit();
L27- }

L28- public static void main(String[] args) throws Exception {
L29-     User1DAO user1DAO = new User1DAO();
L30-     user1DAO.modifyUser();
L31-     user1DAO.modifyUser2();
L32- }
L33- }
    加一个modifyUser2方法,modifyUser方法没有事务提交,没有关闭Session,接着执行modifyUser2,modifyUser2里创建一个新的Session实例se2,想用se2取数据,取不出来,程序一直停在那里。。。
另外还要注意一下Hibernate的锁(乐观的和悲观的)。
注:有一个存疑,这里第17、18行把tx.commit()和 se.close()注释掉了,但是如果把se.close()注释打开,tx.commit()依然注释着,修改的数据更新到数据库了,并且提交 了,modifyUser2也可以读出来数据了,好像tx.commit()会自动调用Transaction.commit(),而且不是调用 Transaction.rollback();这个还要请大家多指教阿。

分享到:
评论

相关推荐

    hibernate的session.flush

    `Session.flush()`方法是一个关键的操作,它强制Hibernate将内存中的对象状态同步到数据库,确保数据的一致性。这篇博客深入探讨了`Session.flush()`的工作原理和应用场景。 `Session`在Hibernate中主要有以下职责...

    hibernate-release-5.0.7.Final.zip官方

    ### Hibernate 5.0.7.Final版本解析与应用指南 #### 一、概述 Hibernate 是一款开源的对象关系映射(Object-...希望这些内容能够帮助开发者更好地理解和使用 Hibernate,从而构建出高效稳定的 Java 应用程序。

    hibernate的flush()、refresh()、clear()针对一级缓存的操作的区别.docx

    在Java的Hibernate框架中,一级缓存是Session对象内置的缓存机制,它的存在是为了优化数据库操作,减少对数据库的直接访问,从而提高应用程序的性能。一级缓存的生命周期与Session对象相同,也就是说,只要Session...

    hibernate-release-5.4.17.Final.zip

    《Hibernate 5.4.17.Final:官方版本详解及应用实践》 Hibernate,作为Java领域中的一个著名对象关系映射(ORM)框架,极大地...通过实际项目中的应用,开发者可以逐步深化对Hibernate的理解,进一步提升编程技能。

    hibernate的flush机制

    在这个例子中,开发者试图通过调用`evict()`方法将`cat`对象从Session中拆离,然后提交事务。然而,由于`evict()`操作将`cat`从`entityEntries`中移除,但在事务提交时(即Flush操作时),Hibernate无法找到`cat`...

    hibernate5--2.数据持久化及事务

    - 使用`Session.flush()`显式触发脏检查,如果发现异常,事务也会回滚。 通过以上内容,我们了解了Hibernate 5在数据持久化和事务管理方面的基本操作和注意事项。在实际项目中,结合事务的隔离级别、锁机制以及适当...

    hibernate--3.Hibernate数据持久化(通过 Session 操纵对象)

    首先,我们需要理解Session在Hibernate中的角色。Session是Hibernate的核心接口之一,它负责对象的持久化操作,比如保存、更新、删除和检索对象。Session对象就像一个临时的工作区域,用于在应用程序和数据库之间...

    hibernate-5.2.15. 最新jar包

    在业务逻辑处理中,通常使用Session的beginTransaction、save/merge、flush和commit等方法来完成数据库操作。 3. **Query和Criteria API**:提供两种方式执行查询,一是HQL(Hibernate Query Language),类似于SQL...

    2022年Hibernate下数据批量处理Java教程.docx

    在 Hibernate 中,使用 Session 的缓存机制可以提高性能,但如果不正确地使用缓存,可能会出现内存溢出错误。例如,如果我们使用 Hibernate 对数据库插入 100,000 条数据,可能会出现内存溢出错误,因为 Hibernate ...

    Hibernatehibernate一级缓存.pdf

    在同一个Session中,对同一个对象进行多次`load()`或`get()`操作,第二次及以后的调用不会执行数据库查询,因为对象已经被缓存。这显示了Hibernate一级缓存如何提高性能,避免重复的数据库访问。 总结起来,...

    Hibernate的事务处理机制和flush方法的用法.docx

    总的来说,理解Hibernate的事务处理机制和`flush`方法的用法是避免异常和确保数据一致性的关键。通过谨慎地管理事务、正确使用`flush`,以及遵循并发控制的最佳实践,我们可以有效地防止和解决这类问题。在复杂的...

    Hibernate code

    `Session`的`flush()`方法则负责将所有缓存在Session中的更改同步到数据库中。 #### 二、何时调用 flush() 在Hibernate中,默认情况下,只有当事务提交时才会自动调用`flush()`方法。然而,在某些情况下可能需要...

    hibernate连接数据[Mysql]的代码实例

    **hibernate连接数据[Mysql]的代码实例** 在Java应用程序中,Hibernate是一个非常流行的ORM(Object-...在`hibernate_mysql`这个压缩包中,可能包含了这些示例的源代码,你可以下载并运行来更深入地理解其工作原理。

    Hibernate下数据批量处理解决方案

    以下是一些关于如何在Hibernate环境下优化批量数据处理的策略。 首先,了解问题的根源。在上述例子中,当尝试向数据库插入100,000条数据时,由于默认情况下Hibernate会将所有持久化对象保留在一级缓存中,随着数据...

    hibernate-release-5.1.16.Final.zip

    2. 更新:调用Session的update()方法,或者直接修改对象属性后调用flush()方法。 3. 删除:使用Session的delete()方法,将对象从数据库中移除。 4. 查询:Criteria API和Query API提供了丰富的查询手段,可以根据...

    Hibernate3[1].2中文参考文档.chm

    《Hibernate3[1].2中文参考文档.chm》是一个关于Hibernate3.1.2版本的中文参考资料,它全面深入地介绍了这个流行的关系对象映射框架。Hibernate是一个Java平台上的开源对象关系映射(ORM)框架,它允许开发人员在不...

    hibernate.properties

    #hibernate.transaction.flush_before_completion ## Enable automatic session close at the end of transaction ## (This setting is relevant with or without the Transaction API) #hibernate.transaction....

    hibernate_reference中文文档.pdf

    - **1.1.7 加载并存储对象**:演示如何使用 Hibernate API 来加载数据库中的数据到 Java 对象,并将 Java 对象持久化到数据库。 ##### 1.2 第二部分 — 关联映射 此章节深入探讨了 Hibernate 中对象之间的关联映射...

    hibernate_flush 深入了解

    1. **对象状态检查**:Hibernate会检查Session中的所有对象,判断它们是否需要被更新、插入或删除。这包括对持久化对象的脏检查,即比较对象的当前状态和上次持久化时的状态。 2. **生成SQL语句**:根据对象的状态...

    域模型的种状态与hibernate缓存PPT学习教案.pptx

    【域模型的状态与Hibernate缓存理解】 在Java的持久化框架Hibernate中,域模型的状态管理是优化数据库操作的关键。域模型通常指的是实体类,如这里的`Customer`类,它们代表数据库中的表记录。域模型有以下几种状态...

Global site tag (gtag.js) - Google Analytics