Всем привет!
Есть такой класс библиотек в Java как mappers. Служат для преобразования одного класса в другой без написания boiler plate кода, в котором:
а) легко допустить ошибку
б) сложно тестировать. Сложно не в плане сложности теста, а из-за того, что постоянно возникает вопрос - а надо ли это тестировать?)
Самым известным mapper-ом в Java является MapStruct. Альтернативы: ModelMapper, Dozer, JMapper, Orica. Если знаете еще - пишите в комментах.
Главная фишка любого mapper - он автоматически копирует значения совпадающих по имени полей, тем самым избавляя от boiler plate кода и потенциальных ошибок.
Также все вышеперечисленные библиотеки умеют работать с вложенными объектами, в частности мапить коллекцию на коллекцию.
Но что делать, если поля не совпадают по имени или по типу? Для этого есть возможность переопределения маппинга для отдельных полей, с указанием нужного имени и преобразования типа.
Но ближе к делу, вот пример маппинга с использованием MapStruct как самой распространенной библиотеки:
@Mapper(componentModel = "spring")
public interface MapStructConverter extends Converter {
@Mapping(source = "status", target = "orderStatus")
Order convert(SourceOrder sourceOrder);
}
Здесь все поля SourceOrder будут скопированы в одноименные поля Order, за исключением поля status, которое станет orderStatus.
Может возникнуть вопрос - это же интерфейс, где исполняемый код?
Код будет сгенерирован при сборке в виде реализации данного интерфейса. Другие вышеперечисленные библиотеки используют либо рефлексию, либо генерация байткода для маппинга.
Главный вопрос - когда это все нужно?
Общий ответ - маппинг модели в DTO или DTO в DTO.
Более конкретный:
1) Полностью совпадающие по полям объекты. Например, это могут быть сгенерированные по разным версиям xsd или Json Schema DTO, хранящие одни и те же данные.
Или если ваши доменные объекты совпадают с DTO. Идеальный кейс для применения mappers.
2) Подвид варианта 1 когда в объектах различаются пару полей.
3) Маппинг коллекций похожих объектов, это тоже boiler plate код. Тут надо смотреть насколько похожи объекты.
Что важно - не использовать библиотеки маппинга для достаточно сильно различающихся объектов, а делать его руками.
Т.к. в таком случае проявляются минусы данных библиотек:
1) этап кодогенерации сам по себе не является злом, но увеличивает сложность сборки. А если вместо генерации используется рефлексия - уменьшается производительность.
2) когда кастомного маппинга становится слишком много, то это усложняет чтение кода. Ты видишь код маппинга, а половины полей там нет...
3) часто кастомный маппинг делается в аннотациях, а это значит что IDEA не подсветит ошибки, они будут видны только во время сборки
P.S. Есть идея сделать статью по сравнению всех вышеперечисленных библиотек.
#java #mappers
Есть такой класс библиотек в Java как mappers. Служат для преобразования одного класса в другой без написания boiler plate кода, в котором:
а) легко допустить ошибку
б) сложно тестировать. Сложно не в плане сложности теста, а из-за того, что постоянно возникает вопрос - а надо ли это тестировать?)
Самым известным mapper-ом в Java является MapStruct. Альтернативы: ModelMapper, Dozer, JMapper, Orica. Если знаете еще - пишите в комментах.
Главная фишка любого mapper - он автоматически копирует значения совпадающих по имени полей, тем самым избавляя от boiler plate кода и потенциальных ошибок.
Также все вышеперечисленные библиотеки умеют работать с вложенными объектами, в частности мапить коллекцию на коллекцию.
Но что делать, если поля не совпадают по имени или по типу? Для этого есть возможность переопределения маппинга для отдельных полей, с указанием нужного имени и преобразования типа.
Но ближе к делу, вот пример маппинга с использованием MapStruct как самой распространенной библиотеки:
@Mapper(componentModel = "spring")
public interface MapStructConverter extends Converter {
@Mapping(source = "status", target = "orderStatus")
Order convert(SourceOrder sourceOrder);
}
Здесь все поля SourceOrder будут скопированы в одноименные поля Order, за исключением поля status, которое станет orderStatus.
Может возникнуть вопрос - это же интерфейс, где исполняемый код?
Код будет сгенерирован при сборке в виде реализации данного интерфейса. Другие вышеперечисленные библиотеки используют либо рефлексию, либо генерация байткода для маппинга.
Главный вопрос - когда это все нужно?
Общий ответ - маппинг модели в DTO или DTO в DTO.
Более конкретный:
1) Полностью совпадающие по полям объекты. Например, это могут быть сгенерированные по разным версиям xsd или Json Schema DTO, хранящие одни и те же данные.
Или если ваши доменные объекты совпадают с DTO. Идеальный кейс для применения mappers.
2) Подвид варианта 1 когда в объектах различаются пару полей.
3) Маппинг коллекций похожих объектов, это тоже boiler plate код. Тут надо смотреть насколько похожи объекты.
Что важно - не использовать библиотеки маппинга для достаточно сильно различающихся объектов, а делать его руками.
Т.к. в таком случае проявляются минусы данных библиотек:
1) этап кодогенерации сам по себе не является злом, но увеличивает сложность сборки. А если вместо генерации используется рефлексия - уменьшается производительность.
2) когда кастомного маппинга становится слишком много, то это усложняет чтение кода. Ты видишь код маппинга, а половины полей там нет...
3) часто кастомный маппинг делается в аннотациях, а это значит что IDEA не подсветит ошибки, они будут видны только во время сборки
P.S. Есть идея сделать статью по сравнению всех вышеперечисленных библиотек.
#java #mappers
Всем привет!
При использовании JPA в проекте может возникнуть вопрос - нужно ли JPA Entity мапить на DTO, а точнее когда это нужно делать?
Вот хорошая статья с ответом на этот вопрос: https://thorben-janssen.com/object-mapper-dto/
#jpa #mappers
При использовании JPA в проекте может возникнуть вопрос - нужно ли JPA Entity мапить на DTO, а точнее когда это нужно делать?
Вот хорошая статья с ответом на этот вопрос: https://thorben-janssen.com/object-mapper-dto/
#jpa #mappers
Thorben Janssen
Think twice before using an object mapping library to get your DTOs
Don't use object mappers to map your entties to DTOs. Here is why...