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.

Другие вопросы по тегам