Я работаю с Glassfish 2.1 с EcipseLink 2.0.0, поэтому действительно использую спецификацию JPA 1.0, и у меня есть EJB без состояния, который находит сущности среди других вещей.Насколько я знаю, JPA 1.0 определяет кэш L1, который работает на уровне контекста постоянства (уровень транзакции для EJB без сохранения состояния), но я не могу понять, почему следующий код выводит «Not same instance», если он находится в той же транзакции.
ЭТО чрезвычайно странно, идентичность объекта обязательно должна поддерживаться внутри транзакции в контексте Java EE.Это очень хорошо задокументировано в JPA wiki book :
Идентификация объекта в Java означает, что две переменные (x, y) ссылаются на тот же логический объект, тогда x == y возвращает true.Это означает, что оба ссылаются на одну и ту же вещь (оба указателя на одну и ту же ячейку памяти).
В JPA идентичность объекта поддерживается внутри транзакции и (обычно) внутри одного и того же EntityManager.Исключение составляет управляемый JEE EntityManager, идентификация объекта поддерживается только внутри транзакции.
Таким образом, в JPA верно следующее:
Employee employee1 = entityManager.find(Employee.class, 123);
Employee employee2 = entityManager.find(Employee.class, 123);
assert (employee1 == employee2);
Это верно независимо от того, как объектДоступ:
Employee employee1 = entityManager.find(Employee.class, 123);
Employee employee2 = employee1.getManagedEmployees().get(0).getManager();
assert (employee1 == employee2);
В JPA идентичность объекта не поддерживается в EntityManager.Каждый EntityManager поддерживает свой собственный контекст постоянства и свое собственное транзакционное состояние своих объектов.
Таким образом, в JPA верно следующее:
EntityManager entityManager1 = factory.createEntityManager();
EntityManager entityManager2 = factory.createEntityManager();
Employee employee1 = entityManager1.find(Employee.class, 123);
Employee employee2 = entityManager2.find(Employee.class, 123);
assert (employee1 != employee2);
Идентификация объекта обычно является хорошей вещью, так какИзбегает, чтобы ваше приложение управляло несколькими копиями объектов, и избегает изменения приложением одной копии, но не другой.Причина, по которой разные EntityManager или транзакции (в JEE) не поддерживают идентичность объекта, заключается в том, что каждая транзакция должна изолировать свои изменения от других пользователей системы.Как правило, это также хорошо, но требует, чтобы приложение знало о копиях, отсоединенных объектах и слиянии.
Некоторые продукты JPA могут иметь концепцию объектов только для чтения, в которой может быть идентифицирована идентичность объекта.поддерживается через EntityManager через общий кэш объектов.
И я не могу воспроизвести проблему с EclipseLink 2.0 в среде Java SE (внутри транзакции и того же EntityManager
) - извините, я выиграл 't test под GF 2.1.
Я даже пробовал со свойством: <property name="eclipselink.cache.type.default" value="Full"/>
в файле persistence.xml
, но делает то же самое
Ничего не значит "Активировать »для кэша L1.
Чего я действительно хотел бы достичь, если это возможно, так это того, чтобы множественные вызовы моего EJB без сохранения состояния возвращали один и тот же экземпляр, другими словами, охватывали бы срок действия кэша JPA между транзакциямии контексты постоянства с использованием EJB без сохранения состояния (...):
Кэш L2 действительно является кешем, охватывающим несколько транзакций, а также EntityManager и L2 cacHing поддерживается большинством провайдеров JPA.Но хотя кэширование L2 уменьшит количество обращений к базе данных, идентичность объекта не гарантируется всеми провайдерами.
Например, в Hibernate кэш L2 не включен по умолчанию, и вы не получите идентификацию объекта, поскольку Hibernate не помещает сами объекты в кэш.
С EclipseLink по умолчанию включен L2 кеш , и вы получите идентификатор объекта в зависимости от типа кеша .По умолчанию используется кэш SOFT-WEAK размером 100 , и он сохраняет идентичность объекта.В то время как вы можете очень точно настраивать вещи (вплоть до уровня сущности), для распределенной среды или нет, все должно работать по умолчанию.
См. Также