Что такое маппер java

Interesting Tasks

воскресенье, 20 октября 2013 г.

Маппинг объектов с помощью java-object-merger

Для чего нужны мапперы объектов?

Простой ответ: чтобы копировать данные автоматически из одного объекта в другой. Но тогда вы можете спросить: зачем нужно это копирование? Можно усомниться, что это нужно очень часто. Значит следует дать более развернутый ответ.
В мире энтерпрайз приложений принято бить внутреннюю структуру на слои: слой доступа к базе, бизнес и представление/веб сервиса. В слое доступа к базе как правило обитают объекты мапящиеся на таблицы в базе. Условимся называть их DTO (от Data transfer object). По хорошему, они только переносят данные из таблиц и не содержат бизнес логики. На слое представления/веб сервисов, находятся объекты, доставляющие данные клиенту (браузер / клиенты веб сервисов). Назовем их VO (от View object). VO могут требовать только часть тех данных, которые есть в DTO, или же агрегировать данные из нескольких DTO. Они могут дополнительно заниматься локализацией или преобразованием данных в удобный для представления вид. Так что передавать DTO сразу на представление не совсем правильно. Так же иногда в бизнес слое выделяют бизнес объекты BO (Business object). Они являются обертками над DTO и содержат бизнес логику работы с ними: сохранение, модифицирование, бизнес операции. На фоне этого возникает задача по переносу данных между объектами из разных слоев. Скажем, замапить часть данных из DTO на VO. Или из VO на BO и потом сохранить то что получилось.

Если решать задачу в лоб, то получается примерно такой “тупой” код:

Мапперы объектов

Чем плох дозер

Какими качествами должен обладать маппер?

Реализация

Перед началом разработки был соблазн написать библиотеку на scala. Т.к. уже был положительный опыт ее использования.

Почему merger а не mapper?

Использование

Программа “Hello world” выглядит примерно так:

Во-первых, видим, что для маппинга необходимо, чтобы у свойства был геттер на обоих объектах. Это нужно для сравнения значений. И сеттер у целевого объекта, чтобы записывать новое значение. Сами свойства должны именоваться одинаково.

Посмотрим же как реализован метод map. Это поможет понять многие вещи о библиотеке.

Если исходный снапшот это бин, и если у него есть identifier, тогда пытаемся найти целевой бин для класса destinationClass используя IBeanFinder-ы [тут createSnapshot(destinationClass, identifier);]. Мы такие не регистрировали, да и identifier-а нет, значит идем дальше. В противном случает бин создается используя подходящий IObjectCreator [тут createSnapshot(destinationClass)]. Мы таких тоже не регистрировали, однако в стандартной поставке имеется создатель объектов конструктором по умолчанию — он и используется. Далее у целевого снапшота берется дифф от снапшота источника и применяется к целевому объекту. Все.

Кстати, дифф, для этого простого случая, будет выглядеть так:

Основные аннотации:

Преобразования типов

В IMergingContext можно регистрировать пользовательские преобразователи типов, из одного типа в другой (интерфейс TypeConverter). Стандартный набор преобразователей включает преобразования:

Источник

Русские Блоги

MAPSTRUCT (использование @Mapper)

2 Введение в MapStruct за 2 минуты

Следующий код демонстрирует, как использовать Map Struct для реализации сопоставления между Java Beans. Предположим, у нас есть класс Car, который представляет автомобиль, а также есть объект передачи данных (DTO) CarDTO.
Эти два класса очень похожи, за исключением того, что имя атрибута как количество отличается, и в объекте Car поле, представляющее тип автомобиля, является перечислением, тогда как в CarDTO напрямую Используйте строковое представление.
Car.java

2.1 Интерфейс картографа
Чтобы сгенерировать средство сопоставления, которое преобразует объекты CarDTO и Car, нам необходимо определить интерфейс сопоставителя.
CarMapper.java

1. Аннотация @Mapper отмечает этот интерфейс как интерфейс сопоставления и является точкой входа процессора MapStruct во время компиляции.

2. Метод, который действительно реализует сопоставление, требует исходный объект в качестве параметра и возвращает целевой объект. Название метода сопоставления произвольно. В случае, когда имена атрибутов в исходном и целевом объекте различаются, эти имена можно настроить с помощью аннотации @Mapping. Мы также можем преобразовать параметры разных типов в исходный тип и целевой тип. Здесь тип перечисления преобразуется в строку через атрибут типа. Конечно, в интерфейсе можно определить несколько методов сопоставления. MapStruct сгенерирует для него реализацию.

3. Реализация автоматически сгенерированного интерфейса может быть получена через объект класса Mapper. По соглашению переменная-член INSTANCE объявляется в интерфейсе, чтобы клиент мог получить доступ к реализации интерфейса Mapper.

2.2 Компиляция

Поскольку MapStruct обрабатывает аннотации в виде подключаемого модуля компилятора Java и генерирует реализацию интерфейса сопоставителя. Следовательно, мы должны вручную скомпилировать его перед его использованием (функция автоматической компиляции IDE не будет использовать функцию подключаемого модуля MapStruct).

Выполните команду maven: mvn compile
Как показано на следующем рисунке, в целевом каталоге имеется более одного класса CarMapperImpl.class:
Этот класс на самом деле является классом реализации, который плагин структуры карты автоматически помогает нам создавать на основе интерфейса CarMapper. Мы можем просмотреть исходный код автоматически созданного класса реализации с помощью функции декомпиляции IDE, как показано на следующем рисунке:

Через декомпилированный исходный код мы можем увидеть это для разных имен атрибутов (seatCount и numberOfSeats) и разных типов атрибутов (типа перечисления и типа строки) Все автоматически помогло нам конвертировать. Для преобразований с разными именами атрибутов мы указываем их с помощью аннотации @Mapping, а преобразования с разными типами атрибутов являются конфигурацией по умолчанию MapStruct. Лично это очень хорошо и очень мощно.

Читайте также:  Что такое нераспространенное предложение 2 класс русский язык

2.3 Использование картографа

Запустите этот модульный тест, если ошибок не было, это означает, что мы успешно выполнили этот кейс!

Источник

Руководство по структуре карты в Java – Расширенная библиотека картографирования

В этой статье мы рассмотрим множество примеров использования MapStruct для расширенного отображения Java, обработки исключений и аннотаций MapStruct.

Вступление

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

Объекты передачи данных (DTOs) регулярно применяются в этих приложениях. DTO-это просто объекты, которые содержат запрошенную информацию о другом объекте. Как правило, объем информации ограничен. Поскольку DTO являются отражением исходных объектов – сопоставители между этими классами играют ключевую роль в процессе преобразования.

В этой статье мы погрузимся в MapStruct – обширный картограф для Java-компонентов.

Структура карты

MapStruct-это генератор кода на основе Java с открытым исходным кодом, который создает код для реализаций сопоставления.

Он использует обработку аннотаций для создания реализаций классов картографов во время компиляции и значительно сокращает объем шаблонного кода, который регулярно писался бы вручную.

Зависимости от структуры карты

Если вы используете Maven, установите MapStruct, добавив зависимость:

Эта зависимость будет импортировать аннотации основной структуры карты. Поскольку MapStruct работает во время компиляции и прикреплен к таким конструкторам, как Maven и Gradle, нам также придется добавить плагин в :

Плагин net.ltgt.apt отвечает за обработку аннотаций. Вы можете применить плагины apt-idea и opt-eclipse в зависимости от вашей СТОРОНЫ.

Основные Сопоставления

У нас есть ЭКЗЕМПЛЯР типа Doctor Mapper|/. Это будет нашей «точкой входа» в экземпляр, как только мы создадим реализацию.

Когда мы создадим/скомпилируем приложение, плагин обработчика аннотаций структуры карты подберет интерфейс Doctor Mapper и сгенерирует для него реализацию:

Сопоставление различных полей источника и цели

Часто модель и технический директор не будут иметь одинаковые имена полей. Могут быть небольшие различия из-за того, что члены команды назначают свои собственные представления, а также из-за того, как вы хотели бы упаковать информацию для службы, которая вызвала DTO.

Разные Имена Свойств

А для Доктора D в давайте добавим специализацию поле:

Теперь нам придется сообщить вашему Доктору Картографу об этом несоответствии. Мы сделаем это, установив флаги источник и цель аннотации @Mapping с обоими этими вариантами:

Специальность область Врача класса соответствует специализации области Врача D к классу.

После компиляции кода обработчик аннотаций сгенерировал эту реализацию:

Несколько Классов Источников

Иногда одного класса недостаточно для создания DTO. Иногда мы хотим объединить значения из нескольких классов в один DTO для конечного пользователя. Это также делается путем установки соответствующих флагов в аннотации @Mapping :

Давайте создадим другую модель Образование :

И добавьте новое поле в Doctor в :

Теперь давайте обновим интерфейс Doctor Mapper :

Сопоставление Дочерних Сущностей

В большинстве случаев POJO не содержат только примитивные типы данных. В большинстве случаев они будут содержать другие классы. Например, у Врача будет 1..n пациентов:

И давайте составим Список из них для Врача :

Поскольку Данные пациента будут переданы, мы также создадим для этого DTO:

И, наконец, давайте обновим Докторскую степень Списком вновь созданного Пациента D до :

Это базовый картограф, который просто отображает пару примитивных типов данных.

Поскольку мы добавили этот флаг, при создании реализации картографа для интерфейса Doctor Mapper MapStruct также преобразует модель Patient в PatientDto – поскольку мы зарегистрировали PatientMapper для этой задачи.

Теперь компиляция приложения приведет к новой реализации:

Обновление Существующих Экземпляров

Иногда мы хотели бы обновить модель с последними значениями от а ДО. Используя аннотацию @MappingTarget на целевом объекте ( Доктор в нашем случае), мы можем обновить существующие экземпляры.

Теперь, после повторного создания реализации, у нас есть метод UpdateModel() :

Что стоит отметить, так это то, что список пациентов также обновляется, поскольку он является дочерней сущностью модуля.

Внедрение Зависимостей

До сих пор мы получали доступ к сгенерированным картам с помощью метода getMapper() :

Давайте обновим наш Doctor Mapper для работы с Spring:

Добавление (ComponentModel) в аннотацию @Mapper сообщает MapStruct, что при создании класса реализации mapper мы хотели бы, чтобы он был создан с поддержкой внедрения зависимостей через Spring. Теперь нет необходимости добавлять поле ЭКЗЕМПЛЯР в интерфейс.

Читайте также:  арамейский язык и иврит в чем разница

Сгенерированный DoctorMapperImpl теперь будет иметь @Компонент аннотацию:

Если вы не используете Spring, MapStruct также поддерживает Java CDI :

Перечисления Отображений

Давайте создадим два перечисления, первое из которых Тип платежа :

Это, скажем, доступные варианты оплаты в приложении. А теперь давайте рассмотрим эти варианты в более общем и ограниченном виде:

Теперь давайте создадим интерфейс сопоставления между этими двумя перечислениями s:

Git Essentials

Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!

MapStruct будет обрабатывать эти случаи:

НАЛИЧНЫЕ и ЧЕК по умолчанию имеют соответствующие значения, в то время как конкретное значение КАРТЫ обрабатывается через переключатель цикл.

Однако этот подход может стать непрактичным, когда у вас есть много значений, которые вы хотели бы присвоить более общему. Вместо того, чтобы назначать каждое из них вручную, мы можем просто позволить MapStruct просмотреть все доступные оставшиеся значения и сопоставить их все с другим.

Это делается с помощью Констант отображения :

Другим вариантом было бы использовать ANY_UNMAPPED :

В этом случае вместо того, чтобы сначала сопоставлять значения по умолчанию, а затем сопоставлять оставшиеся значения с одной целью – MapStruct просто сопоставит все не сопоставленные значения с целью.

Типы данных Сопоставления

MapStruct поддерживает преобразование типов данных между исходным и целевым свойствами. Он также обеспечивает автоматическое преобразование типов между примитивными типами и соответствующими им оболочками.

Автоматическое преобразование типов применяется к:

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

С другой стороны, скажем, наш Пациент объект имеет дату Рождения типа Строка :

Теперь давайте продолжим и сделаем сопоставление между этими двумя:

При преобразовании между датами мы также можем использовать флаг формат данных для установки спецификатора формата. Сгенерированная реализация будет выглядеть следующим образом:

Добавление Пользовательских Методов

Этот объект построен из объектов Доктор и Образование с использованием шаблона проектирования Builder.

Эта реализация будет доступна для использования после того, как класс реализации mapper будет создан MapStruct. Вы можете получить к нему доступ так же, как и к любому другому методу сопоставления:

Создание Пользовательских Картографов

Давайте перепишем предыдущий пример, хотя на этот раз мы сделаем его абстрактным классом:

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

@До сопоставления и @после сопоставления

Давайте добавим эти методы в наш Doctor CustomMapper :

Теперь давайте создадим картограф на основе этого класса:

Добавление Значений По Умолчанию

Давайте обновим наш Doctor Mapper с константой и по умолчанию :

Давайте сгенерируем картограф:

Добавление выражений Java

Наша Доктор модель будет выглядеть так:

И Врачи будут выглядеть так:

А теперь давайте обновим наш Доктор Картограф :

Сгенерированный картограф будет выглядеть следующим образом:

Внешний идентификатор имеет значение:

Обработка исключений при сопоставлении

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

Теперь давайте создадим реализацию для этого картографа:

MapStruct автоматически установил идентификатор врачей с результатом Валидатора экземпляра. Он также добавил предложение throws для метода.

Конфигурации Отображения

MapStruct предоставляет некоторые очень полезные настройки для написания методов сопоставления. В большинстве случаев конфигурации сопоставления, которые мы указываем для метода сопоставления, реплицируются при добавлении другого метода сопоставления для аналогичных типов.

Вместо того, чтобы настраивать их вручную, мы можем настроить аналогичные типы так, чтобы они имели одинаковые/похожие методы сопоставления.

Наследование Конфигурации

Допустим, у нас есть другой картограф, который генерирует Doctor из Doctor D в :

Наследование Обратной Конфигурации

Вместо того, чтобы писать это два раза, мы можем использовать аннотацию @InheritInverseConfiguration для второго метода:

Сгенерированный код из обеих реализаций картографа будет одинаковым.

Вывод

В этой статье мы рассмотрели MapStruct – библиотеку для создания классов картографов, начиная с сопоставлений базового уровня и заканчивая пользовательскими методами и пользовательскими картографами. Мы также рассмотрели различные варианты, предоставляемые MapStruct, включая внедрение зависимостей, сопоставления типов данных, сопоставления перечислений и использование выражений.

MapStruct предоставляет мощный интеграционный плагин для уменьшения объема кода, который пользователь должен написать, и упрощает и ускоряет процесс создания картографов.

Источник

Картографические списки с ModelMapper

Узнайте, как сопоставить списки различных типов элементов с помощью Model Mapper.

Картографические списки с ModelMapper

1. Обзор

2. Модель Mapper

Основная роль ModelMapper заключается в картировании объектов путем определения того, как одна модель объекта отображается на другой, называемой объектом преобразования данных (DTO).

Читайте также:  yigga что за бренд

2.1. Конфигурация

2.2. Тип токена

МодельМаппер использует ТипТокен для карты общих типов. Чтобы понять, почему это необходимо, давайте посмотрим, что происходит, когда мы целое число список характер список:

Далее, если распечатать элементы символы список мы хотели бы видеть пустой список. Это связано с возникновением стирания типа во время выполнения времени выполнения.

Во время компиляции ТокенТип анонимный внутренний случай сохраняет Список тип параметра, и на этот раз наше преобразование является успешным.

3. Использование пользовательского типа отображения

Списки в Java можно отобразить с помощью пользовательских типов элементов.

Например, предположим, что мы хотим составить карту список Пользователь сущностей к ПользовательDTO список. Для достижения этой цели мы назовем карта для каждого элемента:

Конечно, с еще несколько работ, мы могли бы сделать общий метод параметризированных:

Таким образом, мы могли бы вместо этого сделать :

4. Тип карты и картирования недвижимости

Конкретные свойства, такие как списки или наборы, могут быть добавлены в Пользователь-UserDTO модель. TypeMap предоставляет метод для явного определения отображения этих свойств. TypeMap объект хранит картографическую информацию определенных типов (классов):

Из созданного TypeMap объект, который мы явно добавить Карта недвижимости ссылаясь на пример ПользователиListConverter класс:

Внутри addMappings метод, отображение выражения позволяет определить источник назначения свойств с выражениями lambda. Наконец, он преобразует список пользователей в полученный список имен пользователей.

5. Заключение

В этом учебнике мы объяснили, как списки отображаются путем манипулирования общими типами в ModelMapper . Мы можем воспользоваться ТипТокен, общее отображение типов и отображение свойств для создания типов списка объектов и сложных карт.

Источник

Преобразование Entity в DTO с помощью ModelMapper

В этой статье мы рассмотрим, как преобразовывать сущности в DTO-объекты с помощью библиотеки ModelMapper.

Пример представляет собой Spring Boot REST API, выдающее список постов и список пользователей. Поскольку пользователь содержит закрытую информацию (пароль, email, роль), то списки выдаются не в том виде, в каком они хранятся в базе, а в виде специальных объектов DTO (Data Transfer Object). Они содержат только те поля, которые нужны на фронтенде.

Maven-зависимость ModelMapper

Чтобы добавить библиотеку в приложение Spring Boot, в POM-файле пропишем:

Бин ModelMapper в конфигурации

Сразу же создадим в конфигурации бин, который будем впоследствии внедрять в контроллер:

Сущности (Entity)

Сущности Post и User находятся в отношении ManyToOne, то есть несколько постов может быть у одного User.

Поля email, password, role и locked передавать на фронтенд нежелательно.

Когда мы передаем список постов, то из всех полей пользователя достаточно оставить только nickname и id:

Также есть список пользователей для администратора, и в нем нужны почти поля User, кроме пароля:

Контроллеры

Перейдем к контроллерам.

PostController — список постов

Как показано в образце JSON выше, PostController выдает список постов с очень сокращенным User — только поля id и nickname.

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

Так что создадим для передачи поста по сети отдельный DTO-объект PostDto. Он отличается от Post тем, что вместо User содержит UserDto — всего с двумя полями пользователя — id и nickname:

Чтобы при сериализации название поля пользователя в JSON оставалось user, (а не userDto), мы аннотировали его с помощью @JsonProperty(«user»).

Теперь осталось преобразовать Post в PostDto. Сделаем это на уровне контроллера. Для этого внедрим в контроллер ModelMapper:

Преобразовать Post в PostDto можно было бы и самостоятельно, создав в Post метод toPostDto(). Но с библиотекой ModelMapper это сделать проще (особенно, когда проект не такой маленький).

Преобразование Post в PostDto с помощью ModelMapper

Собственно преобразование тут в двух строках.

Преобразование User в UserDto:

ModelMapper сопоставляет те поля User и Post, которые есть в UserDto и PostDto, остальные — игнорирует. Вложенный объект автоматически не сопоставляется.

Вообще ModelMapper — довольно умная библиотека, в ней можно настроить несколько режимов сопоставления, в том числе она распознает нестрогие соответствия названий полей.

MapperUtil.convertList — это утилита для преобразования списка, она просто делает конвертацию для всех элементов списка, принимая в качестве аргумента функцию-конвертер для одного элемента:

UserController — список пользователей

Аналогично внедряем ModelMapper в UserController:

Но здесь уже не будем создавать отдельный UserDto для передачи пользователя без пароля. Вместо этого просто обнулим поле пароля.

Преобразование User в User без пароля

Можно было бы просто присвоить user.password=null, но для демонстрации возможностей ModelMapper сделаем это с помощью него. Чтобы ModelMapper пропустил поле password, настроим маппинг перед конвертацией:

Аналогично преобразовываем все элементы списка с помощью утилиты MapperUtil.convertList.

Чтобы нулевое поле пароля не шло в JSON, аннотируем его:

Итоги

Мы рассмотрели шаблон Data Transfer Object в REST API, реализовав его с помощью ModelMapper. Показана лишь малая часть возможностей ModelMapper, на самом деле он гораздо мощнее.

Источник

Информ портал о технике и не только