什么是grails中的“分离”实例?

时间:2013-09-14 18:35:04

标签: hibernate grails

什么是grails中的分离内容。 ?

请举例说明。

提前致谢。

3 个答案:

答案 0 :(得分:9)

当你创建一个新的域类实例(例如def u = new User(username: 'me')时,Hibernate对此一无所知。但是当你坚持它时,例如当你调用save()时,Hibernate会将插入推送到数据库并将其与当前的Hibernate会话相关联(不要与HTTP会话混淆 - 它们完全不同)。

此外,当您从数据库加载实例时,无论是单独加载还是作为多个结果列表的一部分,您都可以访问该实例,但它也与当前会话相关联。这些对象“附加”到会话中。

这在几个方面很有用。一个是作为第一级缓存。当您致电get时,例如def user = User.get(123),它被检索并附加。但是如果再次使用相同的id调用get,则会从缓存中检索它,并且不需要额外的数据库调用。另一个是脏检查。 Hibernate还会缓存检索到的原始数据,因此当您修改一个或多个字段时,它可以知道已更改的内容(如果有的话)。

对象变为断开连接的一个问题是延迟加载。在HTTP会话中存储对象是很常见的,但是一旦Hibernate会话关闭(例如在请求结束时),所有附加的对象都会被分离。如果您有一个延迟加载的实例或集合未初始化,并且稍后从HTTP会话中检索实例并尝试访问延迟数据,则会导致异常,因为实例已断开连接且无法连接到数据库以检索懒惰的数据。解决此问题的一个方法是将实例重新附加到当前会话 - 请参阅http://grails.org/doc/latest/ref/Domain%20Classes/attach.html。更好的解决方法是不在会话中存储这样的对象,而是仅存储id,并在需要时重新加载实例。

答案 1 :(得分:1)

这只是意味着它不再与Hibernate会话相关联。

答案 2 :(得分:0)

与Session无关的持久化类的新实例在数据库中没有表示,Hibernate没有标识符值被认为是瞬态的:

Person person = new Person();
person.setName("Foobar");

//人处于短暂状态

持久化实例在数据库中具有表示形式,标识符值并与会话相关联。您可以通过将瞬态实例与会话相关联来使其持久化:

Long id = (Long) session.save(person);
// person is now in a persistent state

现在,如果我们关闭Hibernate会话,持久化实例将成为一个分离的实例:它不再连接到Session(但仍然可以修改并稍后重新连接到新的Session)。

所有这一切都清楚地解释了整个第10章。Working with objects of the Hibernate documentation我只是在上面解释。绝对是必读的。