【问题标题】:Is it a good idea to close and open hibernate sessions frequently?经常关闭和打开休眠会话是个好主意吗?
【发布时间】:2010-04-15 05:52:59
【问题描述】:

我正在开发一个应用程序,该应用程序需要以频繁的时间间隔或触发器从数据库中读取实体的状态。但是,一旦 hibernate 读取状态,它就不会重新读取它,除非我明确关闭会话并在新会话中读取实体。

每次我想读取实体时打开会话然后关闭它是个好主意吗?这会给应用程序和数据库带来多少开销(我们也使用 c3p0 连接池)?

在再次读取之前简单地将实体从会话中逐出就足够了吗?

【问题讨论】:

    标签: java hibernate orm


    【解决方案1】:

    您也可以使用refresh 重新加载实体。或者@Bozho 提到的evictclear

    使用连接池,打开和关闭会话的开销并不大。需要时间的是构建会话工厂。

    如果我没记错的话,关闭和重新打开会话的问题是已经加载的对象仍然会分离。这对于延迟加载可能是有问题的。所以最好保持会话打开并使用evictclearrefresh

    请注意,如果您驱逐实体,并访问一个已加载的此类实体,您仍将获得旧数据。

    MyEntity e = session.load( ... );
    ...
    session.evict(e);         // remove entity from the cache
    String p = e.myProperty;  // still the value at the time it was loaded
    e = sesssion.load( ... ); // latest value
    

    在您的情况下,最好引入一个设计指南,说明只要实体被操纵,就应该首先刷新它。

    MyEntity e = session.load( ... );
    ...
    session.refresh( e );     // refresh entity and cache
    String p = e.myProperty;  // latest value
    e = sesssion.load( ... ); // latest value
    

    上面的代码只是伪代码,我没有查过。

    请注意,如果会话打开一段时间,缓存可能会增长,在这种情况下,您可能希望仍然clear 它。一般来说,最好保持会话短,以防止缓存增长的问题,以及连接超时、事务超时和锁争用的问题。

    【讨论】:

      【解决方案2】:

      是的。 evict() 对象。如果你想清除整个会话,clear()它。

      新会话应与请求(线程)或较长时间的会话相关联。

      【讨论】:

      • 您能否提供一些参考资料来阅读有关会话关联及其成本的信息?我用谷歌搜索它没有太多运气。
      【解决方案3】:

      对于链接到其他表的列,如果您将 fetchtype 设置为 LAZY,Hibernate 将不会加载该数据,直到它被明确要求。这样可以节省很多时间。

      Table 中的列可以被标记:

      @ManyToOne(fetch=FetchType.LAZY)
      @JoinColumn(name="other_table_id", nullable = false)
      private OtherTable otherTable;
      

      因此,直到您执行Table.getOtherTable().getValue() 之类的操作,OtherTable 才会加载到会话中。所以如果你不做那件事,你也不需要驱逐它。

      请注意,这是伪代码,您的程序可能看起来有些不同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-10
        • 2016-05-17
        相关资源
        最近更新 更多