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:
Buildscript kullanımı
Pluginin birçok konfigürasyon parametresi bulunmaktadır. Proje içerisinde kullanımı ve parametreler aşağıdaki gibidir.
Konfigurasyon yapısı#
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ündemapstructisimli 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.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:
- 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);
}
- generateMapStructMapper task'ı kullanılarak Mapper'lar otomatik oluşturulur.
 

- 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;
    }
}
- 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
- https://mapstruct.org/documentation/reference-guide/
 - https://mapstruct.org/documentation/stable/reference/html/
 
Örnek Proje
Örnek olarak hvl-javalt-samples repository'si incelenebilir.