JPA EntityManager кеширование
У меня есть сущность, определенная следующим образом:
public class Version {
@Id
private Long id;
private String content;
@Transient
private Model model;
//...
}
Из того, что я вижу, когда find
операция выполняется на Entity Manager, он делает SELECT
в базовой базе данных только один раз, а затем объект кэшируется в Entity Manager. Тем не менее, я вижу, что если я назначу Model
к model
свойство, это изменение не отражается в кэшированном объекте. Например, если за один звонок find
операция выполнена и Model
назначается, когда я делаю find
снова из другого EJB, model
свойство null
снова. Это изменение не отражается в кэшированном объекте? Возможно, потому что это @Transient
?
3 ответа
Менеджер сущностей поддерживает кэш первого уровня, и этот кэш первого уровня выбрасывается, как только транзакция завершается. Иначе, кеш будет возвращать устаревшие значения, поскольку другие транзакции в том же приложении или в другом могут изменять или удалять кэшированные объекты.
Кроме того, каждая параллельная транзакция имеет свой собственный кэш уровня сеанса и, таким образом, свой собственный экземпляр одного и того же объекта.
Если в последующей транзакции вы find
та же сущность, будет выдан новый запрос SQL, и будет возвращен другой экземпляр сущности.
Если что-то должно быть запомнено в транзакциях для данного объекта, то оно должно быть постоянным в базе данных. Это точка базы данных.
Я должен не согласиться с @JB Низет. EntityManager и Siber в JPA предлагают расширенный контекст сохраняемости. Совсем не правда, что "кэш первого уровня выбрасывается сразу после завершения транзакции".
Контекст постоянства может быть либо с областью действия транзакции - контекст постоянства "живет" на протяжении транзакции, либо с расширенным - контекст постоянства охватывает несколько транзакций.
https://web.archive.org/web/20131212234524/https://blogs.oracle.com/carolmcdonald/entry/jpa_caching
Решение, однако, является правильным, вы должны сохранить изменения в объекте, если вы хотите, чтобы он был изменен в кэше.
Если вы используете EclipseLink, то объединение в общий кэш переходных процессов можно настроить двумя способами.
Если используется @CloneCopyPolicy, то объект из контекста постоянства будет клонирован в общий кэш, сохраняя переходные поля.
Если используется @InstantiationCopyPolicy, то для общего кэша будет создан новый экземпляр, а переходные процессы не будут сохранены.
Если вы используете плетение и доступ к полям, то по умолчанию используется @CloneCopyPolicy, в противном случае @InstantiationCopyPolicy. Вы также можете настроить это с помощью
Вы также можете контролировать то, что объединяется в общий кеш, используя DescriptorEventListener и события postMerge/postClone.