简体   繁体   English

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

[英]Is it a good idea to close and open hibernate sessions frequently?

I'm developing an application which requires that state of entities be read from a database at frequent intervals or triggers. 我正在开发一个应用程序,它要求以频繁的间隔或触发器从数据库中读取实体状态。 However, once hibernate reads the state, it doesn't re-read it unless I explicitly close the session and read the entity in a new session. 但是,一旦hibernate读取状态,它就不会重新读取它,除非我明确关闭会话并在新会话中读取实体。

Is it a good idea to open a session everytime I want to read the entity and then close it afterwards? 每次我想要读取实体然后关闭它时打开一个会话是一个好主意吗? How much of an overhead does this put on the application and the database (we use a c3p0 connection pool also)? 这会给应用程序和数据库带来多少开销(我们也使用c3p0连接池)?

Will it be enough to simply evict the entity from the session before reading it again? 在再次阅读之前简单地从会话中逐出实体是否足够?

You can also use refresh to reload the entity. 您还可以使用refresh来重新加载实体。 Or evict and clear , as mentioned by @Bozho. evictclear ,由@Bozho提及。

With a connection pool, the overhead to open and close session isn't big. 使用连接池,打开和关闭会话的开销并不大。 What takes time is to construct the session factory. 需要时间的是构建会话工厂。

The problem with closing and re-opening a session is that object already loaded will still become detached, if I remember well. 关闭并重新打开会话的问题是,如果我记得很清楚,已经加载的对象仍然会分离。 This can be problematic wrt to lazy loading. 对于延迟加载,这可能是有问题的。 So it's better to keep the session open and use evict , clear or refresh . 所以最好保持会话开放并使用evictclearrefresh

Note that if you evict the entity, and you access one such entity already loaded, you will still get the old data. 请注意,如果您逐出实体,并且访问已加载的一个此类实体,您仍将获得旧数据。

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

In you case, it might be better to introduce a design guideline that says that anytime the entity is manipulated, it should be refreshed first. 在您的情况下,最好引入一个设计指南,表明无论何时操作实体,都应该首先刷新它。

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

The code above is only pseudo-code, I haven't checked it. 上面的代码只是伪代码,我没有检查过。

Note that if the session is opened for a certain time, the cache may grow, in which case you may want to still clear it. 请注意,如果会话打开一段时间,缓存可能会增长,在这种情况下,您可能仍希望clear它。 Generally speaking, it's however better to keep the session short to prevent this problem of cache growth, plus problems with connection timeout, transaction timeout, and lock contention. 一般来说,最好保持会话简短以防止缓存增长问题,加上连接超时,事务超时和锁争用问题。

Yes. 是。 evict() the object. evict()对象。 If you want to clear the entire session, clear() it. 如果要清除整个会话,请clear()它。

A new session should be associated with either a request (thread) or a longer-running conversation. 新会话应与请求(线程)或长时间运行的会话相关联。

For columns that link to other tables, if you set the fetchtype to LAZY Hibernate won't load that data until it is explicitly asked for. 对于链接到其他表的列,如果将fetchtype设置为LAZY,则在明确要求之前,Hibernate不会加载该数据。 This saves a lot of time. 这节省了大量时间。

A column in Table could be marked: Table的列可以标记为:

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

So, not until you do something like Table.getOtherTable().getValue() will the OtherTable be loaded into the session. 因此,直到你执行类似Table.getOtherTable().getValue()的操作OtherTable Table.getOtherTable().getValue()才会将OtherTable加载到会话中。 So if you don't do something that, you also don't need to evict it. 因此,如果你不做某些事情,你也不需要驱逐它。

Please note that this is pseudocodish and might look a little different for your program. 请注意,这是伪编码,可能会对您的程序有所不同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM