2010-04-15 79 views
2

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

每次我想要读取实体并在事后关闭它时打开一个会话是否是个好主意?这会对应用程序和数据库造成多大的开销(我们也使用c3p0连接池)?

在再次读取它之前,仅仅从会话中逐出实体就足够了吗?

回答

3

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

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

关闭并重新打开一个会话的问题是,如果我记得没错,那么已经加载的对象仍然会被分离。这可能会导致延迟加载的问题。因此,最好保持会议开放并使用evict,clearrefresh

请注意,如果您驱逐实体,并且您访问了一个已经加载的实体,您仍然会获得旧数据。

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它。一般来说,最好保持会话不变以防止缓存增长问题,以及连接超时,事务超时和锁定争用问题。

0

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

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

+0

你能否提供一些参考资料来阅读关于会话关联和它的成本?我用google搜索了它,但没有多少运气。 – Gaurav 2010-04-15 06:37:01

0

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

Table A柱可标明:

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

所以,直到你做的东西像Table.getOtherTable().getValue()OtherTable被加载到会话。所以如果你不这样做,你也不需要驱逐它。

请注意,这是伪科技,可能看起来有点不同,您的程序。