Подтвердить что ты не робот

Отключить кеширование в JPA (eclipselink)

Я хочу использовать JPA (eclipselink) для получения данных из моей базы данных. База данных изменяется рядом других источников, и поэтому я хочу вернуться к базе данных для каждого найденного мной поиска. Я прочитал несколько сообщений об отключении кеша, но это, похоже, не работает. Любые идеи?

Я пытаюсь выполнить следующий код:

        EntityManagerFactory entityManagerFactory =  Persistence.createEntityManagerFactory("default");
        EntityManager em = entityManagerFactory.createEntityManager();

        MyLocation one = em.createNamedQuery("MyLocation.findMyLoc").getResultList().get(0);

        MyLocation two = em.createNamedQuery("MyLocation.findMyLoc").getResultList().get(0);    

        System.out.println(one==two);

one == two истинно, пока я хочу, чтобы он был ложным.

Я попытался добавить все/все следующие в мой persistence.xml

<property name="eclipselink.cache.shared.default" value="false"/>
<property name="eclipselink.cache.size.default" value="0"/>
<property name="eclipselink.cache.type.default" value="None"/>

Я также попытался добавить аннотацию @Cache к самому Entity:

@Cache(
  type=CacheType.NONE, // Cache nothing
  expiry=0,
  alwaysRefresh=true
)

Я что-то недопонимаю?

4b9b3361

Ответ 1

Это поведение является правильным, иначе, если вы измените объект один и объект два с разными значениями, у вас будут проблемы при их сохранении. То, что происходит, это вызов для загрузки объекта двумя обновлениями объекта, загруженного при первом вызове. Они должны указывать на один и тот же объект, поскольку они являются одним и тем же объектом. Это гарантирует, что грязные данные не могут быть записаны.

Если вы вызываете em.clear() между двумя вызовами, сущность должна отделиться, ваша проверка вернет false. Тем не менее, нет необходимости в этом, ссылка eclipse действительно обновляет ваши данные до последней, которые, как я думаю, это то, что вы хотите, так как это часто меняется.

Если вы хотите обновить эти данные с помощью JPA, вам нужно будет получить пессимистические блокировки в Entity, чтобы базовая данные не могут быть изменены в БД.

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

В вашем коде:

em.createNamedQuery("MyLocation.findMyLoc").setHint(QueryHints.CACHE_USAGE, CacheUsage.DoNotCheckCache).getResultList().get(0);

Или в файле persistence.xml:

<property name="eclipselink.query-results-cache" value="false"/>

Ответ 2

final Query readQuery = this.entityManager.createQuery(selectQuery);
readQuery.setParameter(paramA, valueA);

// Update the JPA session cache with objects that the query returns.
// Hence the entity objects in the returned collection always updated.
readQuery.setHint(QueryHints.REFRESH, HintValues.TRUE);

entityList = readQuery.getResultList();

Это работает для меня.

Ответ 3

См,

http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching

Для того же EntityManager JPA всегда требуется, чтобы один == два, так что это правильно, неважно, каковы ваши параметры кэширования (это кеш L1 или транзакционный кеш, который обеспечивает изоляцию транзакции и поддерживает идентификацию объекта).

Чтобы заставить запрос обновляться (и возвращать сделанные вами изменения), вы можете использовать подсказку запроса "eclipselink.refresh" = "true". Или, вероятно, лучше, используйте новый EntityManager для каждого запроса/запроса или вызовите clear() в EntityManager.

<property name="eclipselink.cache.shared.default" value="false"/>

Правильный способ отключить общий кэш (кеш L2). Удалите все остальные настройки, поскольку они неправильны и могут вызвать проблемы.

EclipseLink по умолчанию не поддерживает кеш запросов, поэтому эти настройки не будут влиять. CacheUsage также неверен, не используйте его (это для запросов в памяти).

Ответ 4

Если вы хотите отключить кеширование без специфики поставщика, вы можете аннотировать свой объект домена:

@Cacheable(false)

Вот пример:

@Entity
@Table(name="SomeEntity")
@Cacheable(false)
public class SomeEntity {
    // ...
}

Ответ 5

Если вручную изменить атрибуты объекта, например MyLocation. Вышеприведенный трюк (CACHE_USAGE=CacheUsage.DoNotCheckCache или eclipselink.query-results-cache=false) не работает, как я пытался.

Итак, я попытался установить еще один намек, который eclipselink.refresh, на true. то это работает. Я имею в виду, что атрибуты, измененные вручную, получаются.

Итак, как я понимаю, вышеупомянутый трюк только гарантирует, что он получает правильные объекты. Однако, если объекты уже кэшированы, eclipselink просто возвращает их, не проверяя свежесть содержимого объектов. Только если для подсказки eclipselink.refresh установлено значение true, будут ли эти объекты обновляться, чтобы отображать последние значения атрибутов.

Ответ 6

Я знаю, что это сообщение может быть старым, но я пишу для других, которым нужна помощь. У меня была эта проблема, и, наконец, я решил ее с помощью этого кода:

em.createNamedQuery("findAll").setHint(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.BYPASS).getResultList();

Это работает очень хорошо. И мы видим, что в javadoc перечисления BYPASS написано, что:

Обход кеша: получить данные непосредственно из базы данных.

Я должен заметить, что я использую Weblogic 12c и TopLink в качестве реализации JPA.

Ответ 7

Кэш первого уровня включен по умолчанию, и его нельзя отключить. т.е. никакие настройки в вашем файле persistence.xml не будут отключены.

Вы можете очистить все объекты диспетчера объектов, вызвав

entityManager.clear()

это приведет к тому, что последующие запросы перейдут в базу данных (в первый раз), а затем объекты снова будут сохранены в кеше

Вы можете заставить каждый запрос обращаться к базе данных напрямую, вызывая

query.setHint("javax.persistence.cache.storeMode", CacheStoreMode.REFRESH);