У меня есть интеграционный тест DAO, в котором я использую общий EntityManager (через Spring, используя SharedEntityManagerCreator). Класс тестирования помечен как @Transactional, как и тестируемый метод DAO.JPA: Всегда ли EntityManager.find() возвращает ту же ссылку на объект для одного и того же ключа?
В обоих тестовом классе и DAO Я retreiving на объект пользователя следующим образом:
User user = em.find(User.class, "test");
В настройках моего теста я модифицировал объект пользователя, но я не видя изменения в DAO, когда тест пришел в действие. Оказалось, что эти две ссылки не относятся к одному и тому же объекту; Я доказал это в своем классе испытаний, используя:
System.out.println("User objects equal = " + (user == dao.getUser()));
Это напечатано неверно. Я бы ожидал, что каждый вызов EntityManager с использованием того же ключа вернет ту же ссылку на объект и был удивлен (и немного встревожен!), Чтобы узнать, что это не так. Может ли кто-нибудь пролить свет на это? Я переработал свой код, поэтому на самом деле это не проблема (у DAO не должно было быть объекта User в любом случае), но я все равно хотел бы это понять лучше.
Спасибо!
Java 1.6u22, TOPLINK Основы 2.0.1, 2.5.6 Spring
axtavt правильный. Когда EntityManager закрыт, связанный с ним контекст сохранения, это сбор мусора. Если ваш экземпляр EntityManager автоматически поставляется контейнером вместе с транзакцией, ваши вызовы в em.find() всегда возвращают один и тот же физический объект для того же первичного ключа, пока одна и та же транзакция (и EntityManager) все еще остается открытый. Если вам нужен EntityManager с более длительным сроком службы, тогда у вас есть возможность использовать управляемый приложениями EntityManager вместо управляемого контейнером, но с некоторой дополнительной работой. –
Я вижу, спасибо за ваши ответы. Я уверен, что есть только одна транзакция, разделяемая как моим тестом, так и моим dao, поскольку методы, аннотированные @Before и @After, включены в аннотацию @Transactional; Журналы Toplink также показывают одну транзакцию. Поэтому, я думаю, я не должен получать тот же EntityManager как в тестовом классе, так и в DAO. Есть ли способ узнать, являются ли два EntityManager одинаковыми? Я знаю, что общий EntityManager, который дает мне Spring, фактически является прокси-сервером, который делегирует вызовы, поэтому я не вижу очевидного способа проверки. – Conan
@Conan: Я проверил его и выяснил, что методы '@ Before' /' @ After' фактически выполняются в той же транзакции, что и '@ Test', поэтому' em.find() 'возвращает те же экземпляры. Возможно, ваша проблема имеет другую причину. Вы можете зарегистрировать 'TransactionSynchronizationManager.getCurrentTransactionName()' для проверки идентичности транзакции. – axtavt