Ana içeriğe geç

Mapstruct Plugin#

Proje içerisinde kullanılan veritabanı nesneleri ile transfer nesnelerinin birbirine dönüştürülmesini sağlamaktadır.

Projelere iki farklı yöntem ile eklenebilmektedir. Yöntemler şunlardır:

DSL kullanımı

build.gradle
plugins {
    id 'hvl-mapstruct-plugin' version hvlMapstructPluginVersion
}

Buildscript kullanımı

build.gradle
buildscript {
    repositories {
        maven {
            url 'http://nexus.bulut.ai/repository/framework-plugin-group/'
        }
    }
    dependencies {
        classpath(group: 'tr.com.havelsan.plugin', name: 'hvl-gradle-mapstruct-plugin')
    }
}

apply plugin: 'hvl-mapstruct-plugin'

Pluginin birçok konfigurasyon parametresi bulunmaktadır. Proje içerisinde kullanımı ve parametreler aşağıdaki gibidir.

Konfigurasyon yapısı#

build.gradle
import tr.com.havelsan.javarch.gradle.mapstruct.plugin.extension.data.HvlMapStructPluginMode

hvlMapStruct {
    mode = HvlMapStructPluginMode.MOVE

    excludeList = [
            '**/**Configuration.java'
    ]
}
  • mode: Mapper implementasyonlarının oluşturulma modudur. Varsayılan değer: MANUEL
    • AUTO: Mapper implementasyonlarını compile aşamasında otomatik olarak oluşturur ve kullanır. Bu ayar seçili iken plugin task'ı oluşmaz.
    • MOVE: Bu ayar seçili iken plugin taskı(generateMapStructMapper) oluşur ve task çalıştırıldığında oluşan mapper implementasyonları otomatik olarak Mapper sınıflarının bulunduğu path'e taşınır.
    • MANUEL: Bu ayar seçili iken plugin taskı(generateMapStructMapper) oluşur ve task çalıştırıldığında oluşan mapper implementasyonları proje kökünde mapstruct isimli bir klasör içerisine taşınır. Dosyaların buradan manuel olarak kopyalanması beklenir.
  • library: (Optional) Mapstruct kütüphane bilgisidir. Varsayılan olarak org.mapstruct:mapstruct:1.4.2.Final değerini kullanmaktadır.
  • annotationProcessorLibrary: (Optional) Mapstruct anotasyon işleyici(annotation processor) kütüphane bilgisidir. Varsayılan olarak org.mapstruct:mapstruct-processor:1.4.2-HVL.Final değerini kullanmaktadır.
  • aptOptions: (Optional List) Mapstruct çalışırken işleyicinin kullandığı ayarların bilgisidir. Varsayılan olarak aşağıdaki değerleri almaktadır.
    [
      'mapstruct.defaultComponentModel=spring',
      'mapstruct.suppressGeneratorVersionInfoComment=true',
      'mapstruct.unmappedTargetPolicy=WARN',
      'mapstruct.defaultInjectionStrategy=constructor',
      'mapstruct.suppressGeneratorTimestamp=true',
    ]
    
  • excludeList: (Optional) Mapstruct çalışırken taranmaması istenen sınıfların bilgisidir. Mapstruct çalışırken compile hatası alınan sınıflar bu listeye eklenip, mapstructın çalışması sağlanabilir. Varsayılan değerler: **/converter/*Impl.java **/*MapperImpl.java

Plugin proje içinde ide üzerinden veya konsol ile kullanılabilir.

Konsol Kullanımı

@Mapper annotation'ına sahip sınıfların implementasyonlarını oluşturmak için kullanılır.

Kullanım şekli: gradle cleanAll build generateMapStructMapper

Ide üzerinden kullanım

ÖRNEK 1:

MusteriModel ve MusteriEntity dönüşümü için yapılması gerekenler:

  1. Mapper interface tanımlanır.
MusteriMapper.java
package tr.com.havelsan.musteri.service.converter;

import org.mapstruct.Mapper;
import tr.com.havelsan.musteri.common.dto.MusteriModel;
import tr.com.havelsan.musteri.service.entity.MusteriEntity;

@Mapper
public interface MusteriMapper {

    MusteriModel musteriEntityToMusteriModel(MusteriEntity entity);

    MusteriEntity musteriModelToMusteriEntity(MusteriModel model);

}
  1. generateMapStructMapper task'ı kullanılarak Mapper'lar otomatik oluşturulur.

  1. MusteriMapperImpl otomatik olarak oluşur
MusteriMapperImpl.java
package tr.com.havelsan.musteri.service.converter;

import javax.annotation.Generated;

import tr.com.havelsan.musteri.common.dto.MusteriModel;
import tr.com.havelsan.musteri.service.entity.MusteriEntity;

@Generated(
        value = "org.mapstruct.ap.MappingProcessor",
        date = "2020-02-14T08:03:32+0300",
        comments = "version: 1.3.1.Final, compiler: javac, environment: Java 1.8.0_192 (Oracle Corporation)"
)
public class MusteriMapperImpl implements MusteriMapper {

    @Override
    public MusteriModel musteriEntityToMusteriModel(MusteriEntity entity) {
        if (entity == null) {
            return null;
        }

        MusteriModel musteriModel = new MusteriModel();

        musteriModel.setId(entity.getId());
        musteriModel.setVersion(entity.getVersion());
        musteriModel.setDateCreated(entity.getDateCreated());
        musteriModel.setDateUpdated(entity.getDateUpdated());
        musteriModel.setCreatedBy(entity.getCreatedBy());
        musteriModel.setUpdatedBy(entity.getUpdatedBy());
        musteriModel.setDeleted(entity.getDeleted());
        musteriModel.setDeletedDate(entity.getDeletedDate());
        musteriModel.setAd(entity.getAd());
        musteriModel.setSoyad(entity.getSoyad());
        musteriModel.setDogumTarihi(entity.getDogumTarihi());
        musteriModel.setKayitTarihi(entity.getKayitTarihi());
        musteriModel.setCinsiyet(entity.getCinsiyet());
        musteriModel.setTip(entity.getTip());
        musteriModel.setUuid(entity.getUuid());

        return musteriModel;
    }

    @Override
    public MusteriEntity musteriModelToMusteriEntity(MusteriModel model) {
        if (model == null) {
            return null;
        }

        MusteriEntity musteriEntity = new MusteriEntity();

        musteriEntity.setId(model.getId());
        musteriEntity.setUuid(model.getUuid());
        musteriEntity.setVersion(model.getVersion());
        musteriEntity.setDateCreated(model.getDateCreated());
        musteriEntity.setDateUpdated(model.getDateUpdated());
        musteriEntity.setCreatedBy(model.getCreatedBy());
        musteriEntity.setUpdatedBy(model.getUpdatedBy());
        musteriEntity.setDeleted(model.getDeleted());
        musteriEntity.setDeletedDate(model.getDeletedDate());
        musteriEntity.setAd(model.getAd());
        musteriEntity.setSoyad(model.getSoyad());
        musteriEntity.setDogumTarihi(model.getDogumTarihi());
        musteriEntity.setKayitTarihi(model.getKayitTarihi());
        musteriEntity.setCinsiyet(model.getCinsiyet());
        musteriEntity.setTip(model.getTip());

        return musteriEntity;
    }
}
  1. Kullanılmak istenen servis içerisine inject edilerek kullanılır.
MusteriServiceImpl.java
public class MusteriServiceImpl implements MusteriService {

    @Autowired
    MusteriMapper musteriMapper;

    // other definitions
    @Override
    @CacheEvict(value = "musteriler", allEntries = true)
    public MusteriModel musteriKaydet(MusteriModel musteriModel) {
        MusteriEntity musteriEntity = musteriRepository.saveAndFlush(musteriMapper.musteriModelToMusteriEntity(musteriModel));
        return musteriMapper.musteriEntityToMusteriModel(musteriEntity);
    }
//other methods
}

ÖRNEK 2:

Proje genelinde kullanılmak üzere EKSEN framework'ten sağlanan GenericMapStructMapper interface'i kullanılabilir.

MusteriModel ve MusteriEnttiy için HvlGenericMapStructMapper dan extend edecek şekilde MusteriMapper tanımlanır.

HvlMapstructSampleDetailMapper.java
package tr.com.havelsan.javarch.samples.mapstruct.converter;

import org.mapstruct.Mapper;
import tr.com.havelsan.javarch.data.model.mapper.HvlGenericMapStructMapper;
import tr.com.havelsan.javarch.samples.mapstruct.entity.HvlMapstructSampleDetail;
import tr.com.havelsan.javarch.samples.mapstruct.model.HvlMapstructSampleDetailModel;

/**
* @author javarch
*/
@Mapper
public interface HvlMapstructSampleDetailMapper extends HvlGenericMapStructMapper<HvlMapstructSampleDetailModel, HvlMapstructSampleDetail> {
}

generateMapStructMapper task'ı çalıştırılır ve mapper implementation elde edilir. HvlGenericMapStructMapper içerisinden gelen methodlar otomatik olarak oluşturulacaktır. Ek olarak eklenen metodlar varsa onları da ekleyecektir.

HvlMapstructSampleDetailMapperImpl.java
package tr.com.havelsan.javarch.samples.mapstruct.converter;

import org.springframework.stereotype.Component;
import tr.com.havelsan.javarch.data.commons.pageable.HvlPage;
import tr.com.havelsan.javarch.samples.mapstruct.entity.HvlMapstructSampleDetail;
import tr.com.havelsan.javarch.samples.mapstruct.model.HvlMapstructSampleDetailModel;

import javax.annotation.processing.Generated;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

@Generated(
        value = "org.mapstruct.ap.MappingProcessor"
)
@Component
public class HvlMapstructSampleDetailMapperImpl implements HvlMapstructSampleDetailMapper {

  @Override
  public HvlMapstructSampleDetailModel convertToModel(HvlMapstructSampleDetail entity) {
    if (entity == null) {
      return null;
    }

    HvlMapstructSampleDetailModel hvlMapstructSampleDetailModel = new HvlMapstructSampleDetailModel();

    hvlMapstructSampleDetailModel.setUuid(entity.getUuid());
    hvlMapstructSampleDetailModel.setVersion(entity.getVersion());
    hvlMapstructSampleDetailModel.setDateCreated(entity.getDateCreated());
    hvlMapstructSampleDetailModel.setDateUpdated(entity.getDateUpdated());
    hvlMapstructSampleDetailModel.setCreatedBy(entity.getCreatedBy());
    hvlMapstructSampleDetailModel.setUpdatedBy(entity.getUpdatedBy());
    hvlMapstructSampleDetailModel.setDeleted(entity.getDeleted());
    hvlMapstructSampleDetailModel.setDeletedDate(entity.getDeletedDate());
    hvlMapstructSampleDetailModel.setId(entity.getId());
    hvlMapstructSampleDetailModel.setCode(entity.getCode());
    hvlMapstructSampleDetailModel.setDescription(entity.getDescription());

    return hvlMapstructSampleDetailModel;
  }

  @Override
  public List<HvlMapstructSampleDetailModel> convertToModelList(List<HvlMapstructSampleDetail> entities) {
    if (entities == null) {
      return null;
    }

    List<HvlMapstructSampleDetailModel> list = new ArrayList<HvlMapstructSampleDetailModel>(entities.size());
    for (HvlMapstructSampleDetail hvlMapstructSampleDetail : entities) {
      list.add(convertToModel(hvlMapstructSampleDetail));
    }

    return list;
  }

  @Override
  public Set<HvlMapstructSampleDetailModel> convertToModelSet(Set<HvlMapstructSampleDetail> entities) {
    if (entities == null) {
      return null;
    }

    Set<HvlMapstructSampleDetailModel> set = new LinkedHashSet<HvlMapstructSampleDetailModel>(Math.max((int) (entities.size() / .75f) + 1, 16));
    for (HvlMapstructSampleDetail hvlMapstructSampleDetail : entities) {
      set.add(convertToModel(hvlMapstructSampleDetail));
    }

    return set;
  }

  @Override
  public HvlPage<HvlMapstructSampleDetailModel> convertToHvlPageModel(HvlPage<HvlMapstructSampleDetail> hvlPageEntity) {
    if (hvlPageEntity == null) {
      return null;
    }

    HvlPage<HvlMapstructSampleDetailModel> hvlPage = new HvlPage<HvlMapstructSampleDetailModel>();

    hvlPage.setData(convertToModelList(hvlPageEntity.getData()));
    hvlPage.setTotalElements(hvlPageEntity.getTotalElements());
    hvlPage.setTotalPages(hvlPageEntity.getTotalPages());
    hvlPage.setPageable(hvlPageEntity.getPageable());

    return hvlPage;
  }

  @Override
  public HvlMapstructSampleDetail convertToEntity(HvlMapstructSampleDetailModel model) {
    if (model == null) {
      return null;
    }

    HvlMapstructSampleDetail hvlMapstructSampleDetail = new HvlMapstructSampleDetail();

    hvlMapstructSampleDetail.setUuid(model.getUuid());
    hvlMapstructSampleDetail.setVersion(model.getVersion());
    hvlMapstructSampleDetail.setDateCreated(model.getDateCreated());
    hvlMapstructSampleDetail.setDateUpdated(model.getDateUpdated());
    hvlMapstructSampleDetail.setCreatedBy(model.getCreatedBy());
    hvlMapstructSampleDetail.setUpdatedBy(model.getUpdatedBy());
    hvlMapstructSampleDetail.setId(model.getId());
    hvlMapstructSampleDetail.setDeleted(model.getDeleted());
    hvlMapstructSampleDetail.setDeletedDate(model.getDeletedDate());
    hvlMapstructSampleDetail.setCode(model.getCode());
    hvlMapstructSampleDetail.setDescription(model.getDescription());

    return hvlMapstructSampleDetail;
  }

  @Override
  public void mapToEntity(HvlMapstructSampleDetailModel model, HvlMapstructSampleDetail entity) {
    if (model == null) {
      return;
    }

    entity.setUuid(model.getUuid());
    entity.setVersion(model.getVersion());
    entity.setDateCreated(model.getDateCreated());
    entity.setDateUpdated(model.getDateUpdated());
    entity.setCreatedBy(model.getCreatedBy());
    entity.setUpdatedBy(model.getUpdatedBy());
    entity.setId(model.getId());
    entity.setDeleted(model.getDeleted());
    entity.setDeletedDate(model.getDeletedDate());
    entity.setCode(model.getCode());
    entity.setDescription(model.getDescription());
  }

  @Override
  public List<HvlMapstructSampleDetail> convertToEntityList(List<HvlMapstructSampleDetailModel> model) {
    if (model == null) {
      return null;
    }

    List<HvlMapstructSampleDetail> list = new ArrayList<HvlMapstructSampleDetail>(model.size());
    for (HvlMapstructSampleDetailModel hvlMapstructSampleDetailModel : model) {
      list.add(convertToEntity(hvlMapstructSampleDetailModel));
    }

    return list;
  }

  @Override
  public Set<HvlMapstructSampleDetail> convertToEntitySet(Set<HvlMapstructSampleDetailModel> model) {
    if (model == null) {
      return null;
    }

    Set<HvlMapstructSampleDetail> set = new LinkedHashSet<HvlMapstructSampleDetail>(Math.max((int) (model.size() / .75f) + 1, 16));
    for (HvlMapstructSampleDetailModel hvlMapstructSampleDetailModel : model) {
      set.add(convertToEntity(hvlMapstructSampleDetailModel));
    }

    return set;
  }
}

Detaylı bilgi için linkler

Örnek Proje

Örnek olarak hvl-javalt-samples repository'si incelenebilir.