2012-01-16 4 views
2

я сущность определяется следующим образом:JPA EntityManager кэширование

public class Version { 
    @Id 
    private Long id; 
    private String content; 
    @Transient 
    private Model model; 

    //... 
} 

Из того, что я могу видеть, когда find операция выполняется на Entity менеджера, он делает SELECT на основной базе данных только один раз, а затем объект кэшируется в Менеджере сущностей. Однако я вижу, что если я присвою Model свойству model, это изменение не будет отражено в кэшированном объекте. Например. если в один звонок, выполняется операция find, и Model присваивается, когда я снова делаю find еще от EJB, model. Недвижимость null снова. Разве это изменение не отражается на кэшированном объекте? Возможно, потому что это @Transient?

ответ

7

Менеджер сущности хранит кеш первого уровня, и этот кеш первого уровня отбрасывается, как только транзакция заканчивается. В противном случае кеш будет возвращать устаревшие значения, поскольку другие транзакции в том же приложении или в другом могут изменять или удалять кэшированные объекты.

Кроме того, для одновременных транзакций каждый из них имеет собственный кеш-уровень сеанса и, следовательно, собственный экземпляр того же объекта.

Если в последующей транзакции вы получите find того же объекта, будет выдан новый SQL-запрос, и будет возвращен другой экземпляр объекта.

Если что-то нужно запомнить за транзакциями для данного объекта, то оно должно быть настойчивым в базе данных. Это точка базы данных.

+0

Спасибо, но я не вижу, что новый SQL-запрос выдается во втором вызове EJB (уровень ведения журнала установлен в FINEST). Управление транзакциями установлено по умолчанию. Что может быть причиной? – Dario

+0

Является ли EJB1 вызывающим EJB2, или у вас есть клиентский вызов EJB1, а затем клиентский вызов EJB2? Вы понимаете, что такое транзакции, когда они начинаются и когда они останавливаются? –

+0

Существует только один EJB, который вызывается через веб-службу. Один и тот же метод выполняет два последовательных вызова веб-службы. В первом вызове я вижу запросы SELECT в журналах. Во втором вызове никаких запросов нет. – Dario

2

Если вы используете EclipseLink, то слияние в общий кэш переходных процессов можно настроить двумя способами.

Если используется @CloneCopyPolicy, объект из контекста персистентности будет клонирован в общий кэш, сохраняя переходные поля.

Если используется @InstantiationCopyPolicy, то для общего кэша будет создан новый экземпляр, а переходные процессы не будут сохранены.

Если вы используете плетение и доступ к полю, то по умолчанию используется @CloneCopyPolicy, иначе @InstantiationCopyPolicy. Вы также можете настроить это с помощью

Вы также можете управлять тем, что объединено в общий кэш, используя события DescriptorEventListener и postMerge/postClone.

2

Я должен не согласиться с @JB Nizet. Сессия EntityManager JPA и сеанс Hibernate предлагают расширенный контекст сохранения. Совсем не совсем так, что «кеш первого уровня отбрасывается, как только транзакция заканчивается».

Постоянство Контекст может быть либо транзакции Scoped-- Постоянство Контекст «живет» по длине сделки, или Extended-- Постоянство Контекст охватывает несколько операций.

https://blogs.oracle.com/carolmcdonald/entry/jpa_caching

Решение, однако, является правильным, вы должны сохраняться изменения объекта, если вы хотите его изменить в кэше.

Смежные вопросы