Перед обновлением сущности в моем приложении Jakarta EE, работающем на GlassFi sh 5.1.0 с EclipseLink 2.7.4 и Derby 10.14.2.0, я сравниваю обновленную сущность с сохраненной сущностью и документирую изменения. Недавно я заметил, что мой код сравнения не работает со свойствами отношений @OneToMany и свойствами @ElementCollection, и я отслеживал проблему с отложенной загрузкой свойств @OneToMany и @ElementCollection. Я смог разрешить использование атрибута fetch следующим образом:
Fetch Eager Entity
@Entity
public class Container implements Serializable {
@OneToMany(mappedBy = "container", fetch = FetchType.EAGER)
private List<AssetSerial> assets;
@ElementCollection (fetch = FetchType.EAGER)
private List<Reference> references;
Я не был полностью доволен этим решением, потому что предположил что разработчики по умолчанию установили эти типы отношений на ленивую загрузку, поэтому я продолжил исследования и был рад найти много ссылок на JPA Entity Graphs. Я немедленно создаю следующий код, чтобы заставить EclipseLink инициализировать мои свойства отложенной загрузки перед документированием изменений сущности.
Entity Graph Entity
@Entity
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
@NamedEntityGraph(
name = "Container.eager",
attributeNodes = {
@NamedAttributeNode("assets"),
@NamedAttributeNode("references") })
public class Container implements Serializable {
Entity Manager Инициализация
@PersistenceContext(unitName = "MYPU")
private EntityManager em;
Метод поиска, который работает только один раз для объекта
Map<String, Object> props = new HashMap<String, Object>();
props.put("javax.persistence.loadgraph", em.getEntityGraph("Container.eager"));
Container managedContainer = em.find(Container.class, updatedContainer.getId(), props);
PersistenceUnitUtil tester = em.getEntityManagerFactory().getPersistenceUnitUtil();
logger.debug("Assets: {}", tester.isLoaded(managedContainer, "assets"));
logger.debug("References: {}", tester.isLoaded(managedContainer, "references"));
К сожалению, тестовые методы isLoaded возвращают true только при первом вызове метод find для указанной сущности c. Второй и последующие моменты времени isLoaded возвращает false. Я боролся с этой проблемой в течение многих часов и решил, что эта проблема заключалась в том, что общий кэш EclipseLink не учитывал подсказку графа сущностей, которую я передавал методу find. Я решил проблему, высвободив сущность из кэша непосредственно перед вызовом поиска, как показано ниже.
Метод поиска, который работает
em.getEntityManagerFactory().getCache().evict(Container.class, updatedContainer.getId());
Map<String, Object> props = new HashMap<String, Object>();
props.put("javax.persistence.loadgraph", em.getEntityGraph("Container.eager"));
Container managedContainer = em.find(Container.class, updatedContainer.getId(), props);
PersistenceUnitUtil tester = em.getEntityManagerFactory().getPersistenceUnitUtil();
logger.debug("Assets: {}", tester.isLoaded(managedContainer, "assets"));
logger.debug("References: {}", tester.isLoaded(managedContainer, "references"));
Теперь тест isLoaded всегда возвращает true, и я могу документировать все изменения в обновленном объекте.
Итак, у меня есть следующие вопросы:
- Почему EclipseLink не учитывает мой граф сущностей?
- Буду ли я сталкиваться с проблемами, вручную выселяющими мою сущность из кеш?
- Есть ли лучший способ заставить EclipseLink инициализировать мои свойства отложенной загрузки?