Java 为什么查询后的flush()会导致数据库更新?

Java 为什么查询后的flush()会导致数据库更新?,java,mysql,hibernate,Java,Mysql,Hibernate,我继承了一个使用Hibernate的应用程序,这是我以前从未使用过的。这个应用程序中的“标准”编码实践(这些家伙在很多方面都是可怕的程序员)是为每个查询/更新创建一个会话,执行查询/更新,然后刷新()并关闭()会话。直到现在我都没有这个问题,但现在我有了。情况是这样的: 在数据库登录时查询UserObject 将UserObject保存到用户webapp会话的web存储中 使用UserObject中的值修改屏幕的外观/行为 2是新的部分-以前的代码保存了一些单独的UserObject属性值,或者

我继承了一个使用Hibernate的应用程序,这是我以前从未使用过的。这个应用程序中的“标准”编码实践(这些家伙在很多方面都是可怕的程序员)是为每个查询/更新创建一个会话,执行查询/更新,然后刷新()并关闭()会话。直到现在我都没有这个问题,但现在我有了。情况是这样的:

  • 在数据库登录时查询UserObject
  • 将UserObject保存到用户webapp会话的web存储中
  • 使用UserObject中的值修改屏幕的外观/行为
  • 2是新的部分-以前的代码保存了一些单独的UserObject属性值,或者在用户单击某个内容后每次操作都查询DB。但是现在我正在内存中存储/保存UserObject,这个表/对象上的其他查询导致数据库挂起更新失败,Hibernate在查询后的flush()期间执行更新失败。为什么Hibernate在查询对象时执行DB更新

    我知道我是一个老派程序员,在那里DB事务很小(打开、读/写、提交/关闭),内部从来没有用户交互,因为这会升级行、表和表空间锁。所以我可能不理解Hibernate持久性是如何工作的,以及它应该如何编码。查询后是否永远不要使用flush()?每个用户webapp登录会话是否应该只有一个“会话”对象?Hibernate持久性是否应该消除实际编写“更新”代码的必要性,因为它将在幕后自动发生?这意味着编码模型是查询hibernate/db/Java对象,让用户修改字段,让代码更新Java对象,然后一个flush()+commit()方法调用更新数据库中的所有内容

    **更新**

    下面是我继承的代码示例。对于每个DB对象,在整个代码中有100多个这样的方法

    public static List<BeanObject> GetObjectList() {
        List<BeanObjec> list = null;
        Session session = factory.openSession();
        try {
            list = (List<BeanObject>) session.createQuery("from BeanObject").list();
        } catch (Exception e) {
            // System.out.println("========="+e.getMessage());
        } finally {
            session.flush();
            session.close();
        }
        return clist;
    }
    
    公共静态列表GetObjectList(){
    List=null;
    Session Session=factory.openSession();
    试一试{
    list=(list)session.createQuery(“来自BeanObject”).list();
    }捕获(例外e){
    //System.out.println(“=============”+e.getMessage());
    }最后{
    session.flush();
    session.close();
    }
    返回clist;
    }
    
    直到最近我试图“抓住”其中一个返回的对象时,这种方法已经运行了好几个月。在web会话Memory中保存该单个对象后,对该方法的另一个调用是.list()调用create 3 objects,这很好,但是flush()调用会为所有3个对象创建SQL更新!为什么hibernate要更新未修改的对象

  • 默认情况下,
    commit
    之前的
    flush
    是多余的,因为它无论如何都会发生

  • 默认情况下,Hibernate不选择更新

  • 一个Hibernate会话应该跨越一个完整的请求处理,这是正确的。但是,从每个请求的单个事务的业务级别语义来看,这应该是显而易见的。其他任何事情都是非常不寻常的,但所有事务仍将发生在同一个会话中,该会话最接近于一个租用的DB连接(尽管不是100%)


  • 要理解Hibernate持久性模型,您需要将您的思维方式从手动DML语句更改为

    Hibernate使所有实体状态转换排队,仅限于。自动刷新将在HQL/JPQL和条件查询执行之前进行刷新,但它不会


    默认的flush-before查询很有用,因为SQL查询应该针对当前运行的事务期间发布的最新更改运行。在本机查询之前,您可能只需要手动刷新,但是对于实体查询,如果您坚持默认的自动刷新模式,Hibernate应该会处理它。

    您不认为Hibernate文档可以回答这些问题吗?DB事务仍应尽可能短(但不能短到会影响数据的一致性)。冲洗是自动的。保存修改后的状态是自动的。每个事务都应该有自己的会话。“每个事务都应该有自己的会话”是指每个web事务或调用DB操作的每个用户单击,对吗?你不是说每个SQL语句都应该有自己的事务,我是说数据库中的每个事务,ACID,它的含义。语句是事务的一部分。HTTP请求可以执行0、1或更多事务。典型的1.感谢你的博客链接-非常有用。请看我上面的更新。在那个特定的用例中,刷新是无用的。我无法想象为什么你会用这种方法看到这些更新,因为你打开了一个新的会话,并且不做任何更改,除非你使用属性级访问类型,而且getter返回的集合与原始集合不同。我在上面发布了一些示例代码,在整个应用程序中,每个SQL语句都有自己的会话。我有一种感觉,这段代码的作者不知道如何使用Hibernate。。。但我仍然想知道为什么Hibernate在查询之后的flush()期间执行UPDATE语句,而没有修改任何对象。