Кешируются ли сущности в jpa по умолчанию?

Я добавляю сущность в свою базу данных, и она отлично работает. Но когда я получаю список, я получаю старую сущность, новые добавленные сущности не отображаются, пока я не разверну приложение и снова разверну его. Это означает, что мои объекты кэшируются по умолчанию? Но я не сделал никаких настроек для кэширования сущностей в моем файле persistence.xml или любом другом таком файле.

Я даже пытался вызвать flush(), refresh() и merge(). Но все же это показывает только старые сущности. Я что-то пропустил? Пожалуйста, помогите мне.

5 ответов

Решение

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

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

Это означает, что мои объекты кэшируются по умолчанию?

JPA 1.0 не определяет кэш L2 ("разделяемый кэш"), JPA 1.0 определяет только кэш L1 ("транзакционный кеш"), но провайдеры JPA могут поддерживать кеш общего объекта, и большинство это делают. Это случай TopLink Essentials, который поддерживает кэш L1 и L2 посредством расширений JPA для кэширования (для JVM).

Теперь, как объяснено в большой статье Понимание кеша TopLink Essentials (GlassFish JPA):

  • Все EntityManager из одного и того же модуля персистентности совместно используют кэш сеанса (так TopLink вызывает кэш 2-го уровня).
  • Кеш сессии включен по умолчанию.
  • Если есть изменения / удаления объектов в контексте постоянства, они синхронизируются с кешем сеанса после зафиксированной транзакции, поэтому состояние кеша сеанса обновляется (или такой кеш вообще не будет использоваться).

Так что должно быть что-то еще не так с вашей настройкой. Вы можете попытаться отключить общий кэш сеанса для целей тестирования (и только для целей тестирования), добавив следующее свойство:

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

Но я был бы удивлен, если это что-то изменит. Как я уже сказал, я думаю, что где-то есть другая проблема.

PS: это не отвечает на вопрос, но, если вы используете GlassFish v3, почему бы вам не использовать EclipseLink?

Обновление: отвечая на комментарий ОП

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

Что ж, если вы не создадите связь между сущностями на уровне Java, JPA не сможет создать ее в базе данных (JPA делает только то, что вы ему сказали). Итак, да, вам нужно создать ссылку и, в случае двунаправленной связи, вам даже нужно установить обе стороны ссылки (например, добавить employee для сбора сотрудников на Department и установить department из Employee).

JPA 2.0 определяет общий (L2) кэш, но не определяет значение по умолчанию. EclipseLink по умолчанию разрешает кэширование, другие провайдеры - нет.

EntityManager всегда будет иметь кэш постоянного контекста (L1), пока вы не вызовете clear() или не создадите новый.

Вы можете отключить общий кеш,

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

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

Для получения дополнительной информации о кэшировании см.

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

Вы используете EntityManager? если нет, попробуйте http://docs.oracle.com/javaee/5/api/javax/persistence/EntityManager.html

Используете ли вы источник данных для управления подключениями к вашей базе данных? Вы должны попробовать это тоже. Это XML, который настроен на вашем сервере. Дайте больше информации о вашей архитектуре, чтобы мы могли помочь вам.

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

<shared-cache-mode>NONE</shared-cache-mode>

это работает!

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