我正在开发一个应用程序,它要求以频繁的间隔或触发器从数据库中读取实体状态。但是,一旦hibernate读取状态,它就不会重新读取它,除非我明确关闭会话并在新会话中读取实体。
每次我想要读取实体然后关闭它时打开一个会话是一个好主意吗?这会给应用程序和数据库带来多少开销(我们也使用c3p0连接池)?
在再次阅读之前简单地从会话中逐出实体是否足够?
答案 0 :(得分:4)
您还可以使用refresh
重新加载实体。或者evict
和clear
,如@Bozho所述。
使用连接池,打开和关闭会话的开销不大。需要时间的是构建会话工厂。
关闭并重新打开会话的问题是,如果我记得很清楚的话,已经加载的对象仍会分离。对于延迟加载,这可能是有问题的。因此,最好保持会话开放并使用evict
,clear
或refresh
。
请注意,如果您逐出实体,并且您访问了已加载的一个此类实体,您仍将获得旧数据。
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
加载到会话中。所以,如果你不做某些事情,你也不需要驱逐它。
请注意,这是伪编码,可能会对您的程序有所不同。