Как запретить eclipse-link извлекать ленивые загруженные атрибуты во время сопоставления DTO?

У меня немного парадоксальный вопрос, но я постараюсь объяснить его как можно более содержательно.

Фон

У меня есть трехуровневая установка приложения, включающая Glassfish 3.1.2.2, JPA 2.0 (eclipse-link 2.3.3), базу данных MySQL и автономный Swing-Client. Я получаю доступ к EJB с помощью JNDI через удаленные интерфейсы. Более того, я использую статическое плетение, чтобы извлечь выгоду из ленивой загрузки сложных отношений. В автономном клиенте Swing я использую группы нагрузки для выборочной выборки только тех отношений, которые мне действительно нужны.

Цель

С целью уменьшения сетевого трафика я планирую преобразовать запрошенные аннотированные объекты базы данных @Entity в DTO (объекты передачи данных, POJO) с помощью этого картограф модели.

Большая проблема

Во время сопоставления @ Entity-Objects с соответствующими DTO осуществляется доступ к средствам доступа каждого поля в @Entity, что, в свою очередь, догоняет все невыбранные (ленивые загруженные косвенные списки) поля из базы данных, что приводит к большим снова объекты.

Моя цель - сопоставить ленивые аннотированные объекты @Entitiy такими, какие они есть, без извлечения намеренно невыбранных отношений, чтобы сохранить объекты как можно меньше, прежде чем они будут сериализованы и переданы удаленному клиенту.

Любые идеи ?

РЕДАКТИРОВАТЬ: я нашел этот поток от кого-то, кто использовал Dozer, я ищу нечто подобное для ModelMapper.

Что я пробовал (безуспешно):

  • Я отсоединил результат запроса от диспетчера сущностей перед сопоставлением (все еще ленивая выборка)
  • очистка и закрытие диспетчера сущностей после запроса и перед сопоставлением DTO (все еще ленивая выборка)
  • объявление запрошенного списка окончательным (чтобы механизм ленивой загрузки не мог

переопределить атрибуты, которые были извлечены позже, но это было так)

Заранее большое спасибо за вашу помощь!


person salocinx    schedule 08.07.2013    source источник


Ответы (3)


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

Либо используйте свой собственный метод копирования, который копирует только желаемые атрибуты, либо вы можете использовать CopyGroups в EclipseLink,

http://wiki.eclipse.org/EclipseLink/Examples/JPA/AttributeGroup#Copy_Examples

person James    schedule 09.07.2013
comment
спасибо, Джеймс, копия работает, как ожидалось, и работает очень быстро. большой :-) - person salocinx; 11.07.2013
comment
После использования copyGroup, если для объекта клонирования вызывается метод получения не скопированного атрибута, я получаю stackoverflowError. Можно ли как-то избежать этого? - person Amrita; 05.01.2017

Независимым от JPA способом было бы использовать PersistenceProvider.isLoadedWithReference (сущность, атрибут) для каждого поля и просто использовать null в DTO, если он не был загружен. Это можно использовать для создания DTO напрямую или в CopyGroup, как предложил Джеймс, для создания уменьшенного экземпляра сущности только из выбранных атрибутов.

person Chris    schedule 09.07.2013
comment
Большое спасибо за ваш ценный совет. Я опробовал ваше предложение с использованием условного сопоставления, но эти сопоставители на основе отражения работают слишком медленно, и поэтому я решил реализовать свои собственные функции копирования с использованием шаблона декоратора. - person salocinx; 11.07.2013
comment
привет Крис, не могли бы вы объяснить, как именно использовать PersistenceProvider? как мне получить контекстную ссылку на объект PersistenceProvider? любой пример кода высоко ценится :-) - person salocinx; 15.08.2013

Вы можете использовать глобальное условие свойства для условного сопоставления свойств, которые не являются ленивыми. Вот пример использования JPA2 PersistenceUnitUtil:

final PersistenceUnitUtil unitUtil = entityManagerFactory.getPersistenceUnitUtil();
modelMapper.getConfiguration().setPropertyCondition(new Condition<Object, Object>() {
  public boolean applies(MappingContext<Object, Object> context) {
    return unitUtil.isLoaded(context.getSource());
  }
});
person Jonathan    schedule 19.11.2014