Bu yazımızda MapStruct isimli Java Bean Mapper
kütüphanesini ve Spring ile kullanımını inceleyeceğiz.
1. Giriş
Kodlama yaparken ihtiyaç duyduğumuz bilgileri nesnelerimizin içerisindeki alanlarda tutarız. Nesneye dayalı programlama paradigmasına göre yaptığımız tüm tasarımlar dış dünya ile iletişim noktasına geldiğimizde birebir örtüşmeyebilir. Devraldığınız bir projede tasarladığınız bir POJO(Plain Old Java Object), veritabanındaki varlık modeliyle(**ER**
: Entity Relationship Model
) örtüşmeyebileceği gibi dış servislerden aldığınız DTO (Data Transfer Object) nesneler de sizin iç tasarımınızla birebir örtüşmeyecektir. Bu gibi durumlarda birden fazla obje katmanları (entity
, DTO
, vb
..) yaratarak kendi kodumuzu dış dünyanın etkilerinden korumaya çalışırız. Ancak her ihtiyaç duyduğumuzda bu nesneleri birbirlerine dönüştürmek geliştirme maliyeti açısından zaman çalan bir işlemdir.
MapStruct bu ihtiyacımızı derleme zamanında kolayca karşılayan ve bizim için mapper sınıfları yaratan bir kütüphane. Arayüzler aracılığıyla kaynak ve hedef **POJO**
sınıflarının nasıl eşitleneceğini tasarlayabilirsiniz. Başka bir yöntem olarak sadece annotationlar kullanarak **Spring**
ile bu işi nasıl inceleyeceğimizi aşağıda inceleyeceğiz.
2. Bağımlılıklar
Maven için pom.xml
dosyasına aşağıdaki bağımlılığı ve yapılandırmayı ekliyoruz.
Bağımlılıkların yanı sıra eklememiz gereken bir yapılandırma daha var. MapStruct derleme zamanında çalışan bir araç. Biz bu yazımızda Spring Boot
ile annotation
’lar aracılığı ile bu toolu nasıl kullanabileceğimizi inceliyoruz. Bu sebeple Spring Boot Maven Plugin’inin annotation processor’lerine MapStruct’ın processor’unu eklememiz lazım. Bu sayede Spring Boot Maven Plugin’i derleme esnasında MapStruct Interface’leri tarayıp birazdan yapacağımız yapılandırmaların yönlendirmesinde yeni sınıflar oluşturulmasını sağlayacak.
3. Klonlayıcı
3.1. POJO Sınıfı
İçerisinde primitive ve complex tiplerin olduğu basit bir sınıf oluşturalım.
3.2. Cloner Arayüzü
clone
isimli metod ile girdisi ve çıktısı aynı olan bir interface ile bir nesnenin yeni hash ile klonunu yaratmanız MapStruct ile oldukça kolay.
“ÖNEMLİ NOT: MapStruct arayüzlerinde tanımladığınız mapperların sınıflarının bytecode’larının oluşması için maven clean install
komutunu çalıştırabilirsiniz. Aksi taktirde Spring byte kodu runtime da bulamayacak ClassNotFoundException: Cannot find implementation for …..Mapper
gibi bir hata verecektir.”
3.3. Test Senaryosu
Bir nesne örneği yaratıp mapper’a klonlattığımızda aynı değerlere sahip yeni bir nesne dönecektir.
4. Kalıtıcı
Herhangi bir kalıtım hiyerarşisinde olmasa dahi aynı isimli alanlara ve getter/setterlara sahip iki sınıf arasında kolay bir dönüşüm yapılabilir.
4.1. POJO Sınıfları
Kaynak sınıf olarak InheritDTO
, hedef sınıf olarak InheritObject
sınıflarını ele alalım.
4.2. Inherit Arayüzü
Farkındaysanız hedef sınıfımızda kaynak sınıfımızda bulunmayan alanlar mevcut. Bu durumda @InheritInverseConfiguration
annotationı ile işaretlediğimiz metod imzasına ait kodlar aynı getter setter’lar ile eşleyebildiği kadar veriyi eşitleyip geri kalanları için default değerlerinde bırakacaklardır. Veya dilerseniz alanlar için default değerleri siz de verebilirsiniz.
4.3. Test Senaryosu
Aşağıdaki testleri çalıştırarak senaryomuzun çalıştığını gözlemleyebiliriz.
5. Alan Alan Eşitleyici
Aynı veri tipindeki farklı field isimlerine sahip sınıfları eşitlemek de mümkündür. Bunun için aşağıdaki sınıfları oluşturalım.
5.1. POJO Sınıfları
Değişken isimlerimiz farklı ancak alan tiplerimiz aynı ise aşağıdaki gibi bir mapper düzenlememiz gereklidir.
5.2. TypeSafe Arayüzü
@Mappings annotation’ı ile tek tek hangi alanın hedef sınıftaki hangi alana eşitlenmesini istediğimizi belirtiyoruz.
5.3. Test Senaryosu
6. Tip Dönüştürücü
Sadece aynı tipte olması gerekmeksizin farklı değerlere ve isimlere sahip sınıfları da birbirlerine dönüştürmemiz mümkündür.
6.1. POJO Sınıfları
6.2. Mapper Arayüzü
Yukarıdaki mapperdaki gibi formatını verdiğimiz bir Instant, Date gibi tarih tiplerinin dönüşümünü sağlamamız mümkün.
6.3. Test Senaryosu
7. Sonuç
Giriş niteliğindeki bu yazının haricinde MapStruct’ın farklı birçok mappingi yapabildiğini hatırlatmakta fayda var. Expression
_’_lar ile mappingler yapabileceğiniz gibi has a
ilişkisine sahip sınıflarda da mappinler yapabilirsiniz. Veya Abstract
sınıflar ile tamamen manuel mapping
ler de yapabilirsiniz.
MapStruct bütün bu özelliklerin dışında Lombok
,Kotlin
, Gradle
, JPA
gibi farklı teknolojiler ve araçlara da destek sağlıyor. Ayrıca Eclipse
ve IntelliJ
gibi popüler IDE
‘lere de uyumlu şekilde çalışabiliyor. Github sayfasında farklı örnekleri de inceleyebilirsiniz.
Java diğer mapper toollarıyla kıyaslandığında MapStruct performansıyla denemeye başlamak için çok şey vaadediyor. Bu kıyaslamalarla ilgili örnek bir yazıya buradan ulaşabilirsiniz.
Projenin kodlarına buradan erişebilirsiniz.