JPA EntityManager 缓存
我有一个实体定义如下:
public class Version {
@Id
private Long id;
private String content;
@Transient
private Model model;
//...
}
据我所知,当在实体管理器上执行 find
操作时,它只会在底层数据库上进行一次 SELECT
操作,并且然后实体被缓存在实体管理器中。但是,我发现如果我将 Model
分配给 model
属性,此更改不会反映到缓存的实体。例如,如果在一次调用中完成了 find
操作并分配了 Model
,那么当我从另一个 EJB 再次进行 find
时,model
属性再次为 null
。此更改是否未反映到缓存的实体?也许是因为它是@Transient?
I have an entity defined as follows:
public class Version {
@Id
private Long id;
private String content;
@Transient
private Model model;
//...
}
From what I can see, when a find
operation is done on Entity Manager, it makes a SELECT
on the underlying database only once, and then the entity is cached in the Entity Manager. However, I see that if I assign a Model
to the model
property, this change is not reflected to the cached entity. E.g. if in one call, a find
operation is done and Model
is assigned, when I do find
again from another EJB, model
property is null
again. Is this change not reflected to the cached entity? Perhaps because it's @Transient
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
实体管理器维护一级缓存,并且一旦事务结束,该一级缓存就被丢弃。否则,缓存将返回过时的值,因为同一应用程序或另一应用程序中的其他事务可能会修改或删除缓存的实体。
此外,每个并发事务都有自己的会话级缓存,因此也有自己的同一实体的实例。
如果在后续事务中,您
找到
相同的实体,则会发出新的 SQL 查询,并返回该实体的不同实例。如果必须在给定实体的事务中记住某些内容,那么应该将其持久保存在数据库中。这就是数据库的意义所在。
The entity manager maintains a first level cache, and this first level cache is thrown away as soon as the transaction has ended. Else, the cache would return stale values, since other transactions, in the same application or in another one, could modify or remove the cached entities.
Moreover, concurrent transactions each have their own session-level cache, and thus their own instance of the same entity.
If in a subsequent transaction, you
find
the same entity, a new SQL query will be issued, and a different instance of the entity will be returned.If something must be remembered across transactions for a given entity, then it should be made persistent in in the database. That's the point of a database.
我不得不不同意@JB Nizet。 JPA 的 EntityManager 和 Hibernate 的 Session 提供了扩展的持久性上下文。 “事务结束后一级缓存就被丢弃”的说法根本不正确。
https://web.archive.org/web/20131212234524/https://blogs.oracle.com/carolmcdonald/entry/jpa_caching
但是解决方案是正确的,您必须保留对对象的更改如果您希望在缓存中更改它。
I have to disagree with @JB Nizet. JPA's EntityManager and Hibernate's Session offer an extended Persistence Context. It is not at all true that "first level cache is thrown away as soon as the transaction has ended".
https://web.archive.org/web/20131212234524/https://blogs.oracle.com/carolmcdonald/entry/jpa_caching
The solution however is correct, you have to persist changes to the object if you want it to be changed in the cache.
如果您使用 EclipseLink,则可以通过两种方式配置瞬态数据合并到共享缓存中。
如果使用@CloneCopyPolicy,则持久上下文中的对象将被克隆到共享缓存中,保留瞬态字段。
如果使用@InstantiationCopyPolicy,则将为共享缓存创建一个新实例,并且不会保留瞬态。
如果您使用编织和字段访问,则默认值为@CloneCopyPolicy,否则为@InstantiationCopyPolicy。您还可以
使用 DescriptorEventListener 和 postMerge/postClone 事件控制合并到共享缓存中的内容。
If you are using EclipseLink then the merge into the shared cache of transients can be configured in two ways.
If a @CloneCopyPolicy is used, then the object from the persistence context will be cloned into the shared cache, preserving the transient fields.
If a @InstantiationCopyPolicy is used, then a new instance will be created for the shared cache, and transients will not be preserved.
If you are using weaving and field access, then the default is @CloneCopyPolicy, otherwise @InstantiationCopyPolicy. You can also configure this using
You can also control what is merged into the shared cache using a DescriptorEventListener and the postMerge/postClone events.