Bu yazıda, Java nesnelerini, JPA ve Hibernate Entitylerini DTO’ya mapping yapan ve dönüştüren MapStruct’ı kullanmayı öğreneceğiz.

Spring Boot projesi Oluşturma

Spring initializr kullanarak spring-boot-dto projemizi oluşturalım.Projenin adı spring-boot-dto,proje grubunu ise com.dto,package isminide com.dto.springbootmapstruct olarak ayarladım.

Uygulamamızı java 8,maven 3.6.0,mapstruct 1.3.1 ve lombok 1.18.10 a göre compile edelim.Properties kısmında java versiyonunu,mapstruct versiyonunu,maven versiyonunu ve lombok versiyonu tanımladık.

<properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <org.mapstruct.version>1.3.1.Final</org.mapstruct.version> <org.projectlombok.version>1.18.10</org.projectlombok.version> <org.apache.maven.plugins.version>3.6.0</org.apache.maven.plugins.version>
</properties>

Plugins alanına maven compiler plugini ekleyerek,uygulamamızı properties alanında belirlediğimiz versiyonlara göre compile edelim.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${org.apache.maven.plugins.version}</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${org.projectlombok.version}</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>${org.mapstruct.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Amapstruct.suppressGeneratorTimestamp=true</arg>
<arg>-Amapstruct.defaultComponentModel=spring</arg>
</compilerArgs>
</configuration>
</plugin>

Proje bağımlılığı olarak spring data jpa ,spring web ,dev tools starter dependecylerini ve lombok dependecyisini ekleyelim.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>

Database olarak ben h2 gömülü databesini kullanacağım.Bunun için h2 deepndecysinide pom.xmle ekliyorum.

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>

MapStruct’ı Projeye Ekleme

MapStruct, bean mapping classları oluşturmak için bir Java anatasyon processordur.

Mapstructuresi projeye eklemek için pom.xmle dependecysi eklenir ve maven-compiler-pluginindeki annotationProcessorPaths değeri yapılandırılır.

Biz compiler pluginideki annotationProcessorPaths değerini zaten yapılandırmıştık.Mapstruct dependecysini projeye ekleyelim.

<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId><version>${org.mapstruct.version}</version>
</dependency>

JPA ile Entity,DTO,Repository ve Service Sınıflarını Tanımlama

com.springbootmapstruct paketi altında model adlı bir paket oluşturalım ve bu paketin içerisine Product adındaki entity clasımızı oluşturalım.

@Data
@Entity
public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String description; private BigDecimal price; @CreationTimestamp private Date createdAt; @UpdateTimestamp private Date updatedAt;
}

Product adlı modelimiz hazır.id alanı her kayıt eklendiğinde otomatik olarak artacaktır.

com.springbootmapstruct paketi altında repository adlı bir paket oluşturalım ve bu paketin içerisine ProductRepository adındaki interfacemizi oluşturalım

public interface ProductRepository extends JpaRepository<Product, Long> {
}

Repository ve Model katmanlarımız hazır olduğuna göre artık service katmanını kodlamaya geçebiliriz.

com.springbootmapstruct paketi altında service adlı bir paket oluşturalım ve bu paketin içerisine dto adındaki bir alt paket oluşturalım.

DTO, Data Transform Objeyi temsil eder, veri girişini ve çıkışını özelleştirmek / toplamak için kullanılan ve böylece remote API’ye yapılan çağrı sayısını azaltan bir design patterndir

dto paketi içerisinde ProductDTO adlı dto clasımızı oluşturalım.

@Data
public class ProductDTO { private String name; private String description; private BigDecimal price;
}

MapStruct Mapper Tanımlama

service paketi içerisinde mapper adlı alt paket oluşturalım.Bu paket içerisinde ProductDTO adlı dto clasımızı,Product entity clasımıza mapleyen ProductMapper interfacesini oluşturalım.

@Mapper
public interface ProductMapper { ProductDTO toProductDTO(Product product); List<ProductDTO> toProductDTOs(List<Product> products); Product toProduct(ProductDTO productDTO);
}

MapStruct’ı kullanmakiçin @Mapper anatosyonu içeren interfaceye zorunlu mapping methotlarını tanımlamamız gerekir.

Burada sadece Entity DTO’ya, DTO’yu Entitye, Entity Listesini DTO’lara dönüştüren basit method signaturelerini tanımladık.MapStruct, uygulamanın inşasında sizin için uygulama kodunu üretecektir.

service paketi içerisinde son olarak service adlı alt paket oluşturalım.Bu paket içerisinde ProductService adlı clasımızı oluşturalım.

@RequiredArgsConstructor
@Service
public class ProductService { private final ProductRepository productRepository; public List<Product> findAll() { return productRepository.findAll(); } public Optional<Product> findById(Long id) { return productRepository.findById(id); } public Product save(Product stock) { return productRepository.save(stock); } public void deleteById(Long id) { productRepository.deleteById(id); }
}

REST APIde MapStruct Kullanımı

com.springbootmapstruct paketi altında controller adlı paket oluşturalım.Bu paket içerisinde rest endpointlerimizin bulunacağı ProductApi clasımızı oluşturalım.

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/v1/products")
public class ProductApi { private final ProductService productService; private final ProductMapper productMapper; @GetMapping public ResponseEntity<List<ProductDTO>> findAll() { return ResponseEntity.ok(productMapper.toProductDTOs(productService.findAll())); } @GetMapping("/{id}") public ResponseEntity<ProductDTO> findById(@PathVariable Long id) { Optional<Product> product = productService.findById(id); return ResponseEntity.ok(productMapper.toProductDTO(product.get())); } @PostMapping public ResponseEntity<ProductDTO> create(@RequestBody ProductDTO productDTO) { productService.save(productMapper.toProduct(productDTO)); return ResponseEntity.status(HttpStatus.CREATED).body(productDTO); } @PutMapping("/{id}") public ResponseEntity<ProductDTO> update(@PathVariable Long id, @RequestBody ProductDTO productDTO) { Product product = productMapper.toProduct(productDTO); product.setId(id); productService.save(product); return ResponseEntity.status(HttpStatus.ACCEPTED).body(productDTO); } @DeleteMapping("/{id}") public ResponseEntity delete(@PathVariable Long id) { productService.deleteById(id); return ResponseEntity.status(HttpStatus.NO_CONTENT).build(); }
}

ProductApi clasımızda gelen ProductDTO dto classını ProductMapper kullanarak Product entityimize mapledik.

Uygulamayı Yapılandırma ve Çalıştırtırma

application.propertiese aşağıdaki ayarları ekleyelim

spring.h2.console.enabled=true
spring.jpa.hibernate.ddl-auto=create
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true

spring.h2.console.enabled=true ile h2 console aktif ettik

spring.jpa.show-sql=true sql komutlarını terminale yazar.

spring.jpa.hibernate.ddl-auto=create JPA / Hibernate kullanarak otomatik olarak sizin için veritabanı ve tablo şeması oluşturmanıza olanak sağlar.

Production ortamında, spring.jpa.hibernate.ddl-auto = validate veya spring.jpa.hibernate.ddl-auto = none (varsayılan) kullanarak DDL Auto özelliğini devre dışı bırakmak isteyebilirsiniz.

Uygulama kullanıma hazır. ./mvnw spring-boot:run komutu ile uygulamamızı çalıştıralım.

Uygulamamız başarılı bir şekilde başladı.Product Tablomuz uygulamamız oluşturulurken ddl üzerinden otomatik olarak oluşturulmaktadır.

Curl komutu ile Apileri Test Etme

Yeni bir product oluşturun.

curl -i -H “Content-Type: application/json” -X POST -d ‘{“name”:”Hello Koding”,”description”: “Simple coding examples and tutorials”,”price”:”1″}’http://localhost:8080/api/v1/products

Tüm ürünleri getirin.

curl -i http://localhost:8080/api/v1/products

Projenin Github Linki : https://github.com/susimsek/spring-boot-dto

Slack Kanalımın Linki;

https://join.slack.com/t/javadevelopercorp58/shared_invite/enQtODM3NzU5NDMzMjA1LWQ1YjFlZGE5MTI0ZDNjZDdlNGE4ZDE4NmM0NTBiODJlMTJiYmZjMjJiZTY3NzI0MTc5ZjJhZmQxN2MyMTlmYjU

Daha fazla konu içeriği ve çeşitliliği istiyorsanız slack kanalımı takip edebilirsiniz.

Responses

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir