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

时间:2014-09-28 16:26:26

标签: java mysql hibernate

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

  1. 在登录时查询数据库中的UserObject
  2. 将UserObject保存到用户webapp会话的Web存储中
  3. 使用UserObject中的值来修改屏幕的外观/行为
  4. 2是新片段 - 之前的代码保存了一些单独的UserObject属性值,或者在用户点击某些内容后的每个操作中每次查询数据库。但是现在我将UserObject存储/保存在内存中,此表/对象上的其他查询会导致数据库挂起Hibernate在查询后的flush()期间执行的更新失败。为什么在简单查询对象时Hibernate会执行数据库更新?

    我知道我是一名老派程序员,数据库事务很小(开放,读/写,提交/关闭),并且从未在内部进行过用户交互,因为这会升级行,表和表空间锁。所以也许我不了解Hibernate持久性如何工作以及如何编码。查询后是否应该使用flush()?每个用户webapp登录会话应该只有一个“会话”对象吗? Hibernate持久性是否应该消除实际编码'更新'的原因,因为它会自动发生在封面下?这意味着编码模型是查询hibernate / db / Java对象,让用户修改字段,是否有更新Java对象的代码,然后一个flush()+ commit()方法调用更新数据库中的所有内容?

    **更新**

    以下是我继承的代码示例。每个数据库对象的代码中都有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;
    }
    

    直到最近,当我试图“抓住”其中一个返回的对象时,这已经好几个月了。一旦将该单个对象保存在web-session-memeory中,对该方法的另一次调用就会使.list()调用创建3个对象,这很好,但是flush()调用会为所有3个对象创建SQL UPDATES!为什么hibernate UPDATING一个未被修改的对象?

2 个答案:

答案 0 :(得分:1)

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

  2. 默认情况下,Hibernate不会SELECT FOR UPDATE;

  3. 你是对的,单个Hibernate会话应该跨越整个请求处理。但是,从每个请求的单个事务的业务级语义来看,这应该是显而易见的。其他任何事情都会非常不寻常,但所有交易都会在同一个会话中进行,最接近一个租用的数据库连接(尽管不是100%)。

答案 1 :(得分:0)

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

Hibernate将所有实体状态转换排队,仅归propagate them during a Session flush。在HQL / JPQL和Criteria查询执行之前,AUTO刷新将刷新,但它might not trigger a flush for native SQL queries

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

相关问题