MapStruct, meta annotations.

У циклі статей про популярний генератор коду Mapstruct будемо розбирати його можливості для спрощення роботи під час написання програмних продуктів.

MapStruct підтримує мета анотації, тому в цій статті поговоримо про те, яким чином можна уніфікувати структуру наших мапперів, щоб не використовувати дублювання коду або повторне написання маппінгу для полів, які є спільними для декількох класів і dto.

Налаштування проекту pom.xml

Припустимо в нашому проекті є класи, які мають декілька спільних полів. Нам потрібно описати маппер, який буде правильно співвідносити назви полів однієї сутності(model) і з класом трансфером(dto – data transfer object).
Для прикладу скористаємося наступними класами:

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(of = "id")
public class BoxModel {
    private Long id;
    private LocalDate creationDate;
    private String name;
    private String label;
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode(of = "id")
public class ShelveModel {
    private Long id;
    private LocalDate creationDate;
    private String name;
    private String weightLimit;
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ShelveDto {
private String id;
private String date;
private String groupName;
private String maxWeight;
}

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class BoxDto {
    private String id;
    private String date;
    private String groupName;
    private String designation;
}

@Data, @Builder, @AllArgsConstructor, @NoArgsConstructor, @EqualsAndHashCode – це анотації від бібліотеки Project Lombok, дану бібліотеку ми не розг в цих статтях, звичайно можна використовувати підхід, де при створенні класу, розробник самостійно генерує всі конструктори, методи, які необхідні.

Як видно з класів BoxModel, ShelveModel в них є спільні поля (id, creationDate, name). Для уникнення дублювання коду, ми використаємо мождивості MapStruct і створимо власну анотацію, яка дозволить мати в одному місці зміни і використовувати їх для маппінгу наших класів таким чином, що не повторювати маппінг однакових полів і логіку роботи, якщо потрібно мати якесь специфічне значення в конкретному полі ( тут ми використаємо варіант із LocalDate.now() коли перемаплюємо об’єкт dto в model).
Додамо наступний код:

@Retention(RetentionPolicy.CLASS)
@Mapping(target = "id", ignore = true)
@Mapping(target = "creationDate", expression = "java(java.time.LocalDate.now())")
@Mapping(target = "name", source = "groupName")
public @interface ToModel {}

Створивши наступну анотацію, будемо використовувати в головному маппері для класів. Відразу визначаємо правила заповнення полів, які необхідні для класів. Тепер можемо написати основний маппер, який буде конвертувати значення отриманні з dto в model і навпаки. Як видно ми використовуємо власну анотацію @ToModel і анотацію @Mapping в якій вказуємо конкретні специфічні поля для кожної пари класів.

  • значення для поля id – ігоноруємо, навіть якщо в dto поле буде присутнє і матиме значення;
  • поле creationDate завжди заповнюємо значенням, яке повертає нам метод now() із LocalDate класу;
  • groupName, яке в даному випадку завжди співпадає з полем name в моделі.

Тепер можемо створити маппер, який буде конвертувати значення отриманні з dto в model і навпаки. Як видно у маппері, використовуючи власну анотацію @ToModel і анотацію @Mapping, можна спростити написання коду, мати одне місце для маппінгу спільних полів, а також можливість маппити окремі поля за допомогою @Mapping.

Search

Popular Posts

  • MapStruct, meta annotations.
    MapStruct, meta annotations.

    У циклі статей про популярний генератор коду Mapstruct будемо розбирати його можливості для спрощення роботи під час написання програмних продуктів. MapStruct підтримує мета анотації, тому в цій статті поговоримо про те, яким чином можна уніфікувати структуру наших мапперів, щоб не використовувати дублювання коду або повторне написання маппінгу для полів, які є спільними для декількох класів…

Categories

Archives