JPA EntityManager caching

坚强是说给别人听的谎言 提交于 2019-12-22 13:54:29

问题


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?


回答1:


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.




回答2:


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".

Persistence Context can be either Transaction Scoped-- the Persistence Context 'lives' for the length of the transaction, or Extended-- the Persistence Context spans multiple transactions.

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.




回答3:


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.



来源:https://stackoverflow.com/questions/8878422/jpa-entitymanager-caching

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!