问题
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