经常关闭和打开hibernate会话是一个好主意吗?

时间:2010-04-15 05:52:59

标签: java hibernate orm

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

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

在再次阅读之前简单地从会话中逐出实体是否足够?

3 个答案:

答案 0 :(得分:4)

您还可以使用refresh重新加载实体。或者evictclear,如@Bozho所述。

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

关闭并重新打开会话的问题是,如果我记得很清楚的话,已经加载的对象仍会分离。对于延迟加载,这可能是有问题的。因此,最好保持会话开放并使用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它。一般来说,最好保持会话简短以防止缓存增长问题,加上连接超时,事务超时和锁争用等问题。

答案 1 :(得分:1)

是。 evict()对象。如果您要清除整个会话,请clear()

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

答案 2 :(得分:0)

对于链接到其他表的列,如果将fetchtype设置为LAZY,则在明确要求之前,Hibernate不会加载该数据。这节省了大量时间。

Table中的列可以标记为:

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

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

请注意,这是伪编码,可能会对您的程序有所不同。