JavaRush /Java-Blog /Random-DE /Der Frühling ist nicht gruselig, eine DTO-Schicht
Павел
Level 11

Der Frühling ist nicht gruselig, eine DTO-Schicht

Veröffentlicht in der Gruppe Random-DE
INHALT DES ARTIKELZYKLUS Wir reden weiter über den Frühling. Heute werden wir das DTO-Muster analysieren. Zum Verständnis können Sie hier lesen . Das Schwierigste an DTO ist, zu verstehen, warum es benötigt wird. Beginnen wir mit der Spekulation über Gemüse und schreiben wir gleichzeitig etwas Code. Vielleicht wird dabei etwas klarer. Erstellen Sie ein Spring-Boot-Projekt und verbinden Sie h2 und Lombok . Erstellen Sie Pakete: Entitäten, Repositorys, Dienste, Dienstprogramme. Erstellen Sie in Entitäten eine Produktentität:
package ru.java.rush.entities;

import lombok.Data;
import lombok.experimental.Accessors;
import org.hibernate.annotations.GenericGenerator;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Accessors(chain = true)
@Entity
@Data
public class ProductEntity {

    @Id
    @Column
    @GenericGenerator(name = "generator", strategy = "increment")
    @GeneratedValue(generator = "generator")
    Integer id;

    @Column
    String name;

    @Column
    Integer purchasePrice;//закупочная цена

}
Implementieren Sie die Klassen ProducRepository, ProducService und die Klasse ItiiateUtil ( ähnlich wie im vorherigen Artikel ). Nehmen wir an, wir haben Kartoffeln zum Großhandelspreis von 20 Rubel pro kg und Karotten für 14 Rubel pro kg gekauft. Wir lagern die gekauften Produkte ein. Fügen wir der Datenbank die folgenden Datensätze hinzu: [Id =1, name= „Kartoffeln“, PurchasePrice = 20] [Id =2, name= „Karotten“, PurchasePrice = 14] Als anständige Spekulanten müssen wir unsere Waren gewinnbringend verkaufen, Dafür verpacken wir es schön und erhöhen den Preis. Das heißt, bei uns stapelte sich schmutziges und unschönes Gemüse, aber es wird saubere vegane Premiumprodukte aus dem Luxussegment geben. Stimmen Sie zu, dies wird nicht mehr dasselbe Produkt (Objekt) sein, das wir in großen Mengen gekauft haben. Erstellen Sie für ein neues Produkt ein DTO-Paket und darin die Klasse ProductDto
package ru.java.rush.dto;

import lombok.Data;

@Data
public class ProductDto {
    Integer id;
    String name;
    Integer purchasePrice;
    String  packaging;//упаковка
    Integer salePrice;//цена реализации
}
ProductDto hat zwei Variablen, die ProductEntity nicht hat: „Verpackung“ und „Verkaufspreis“. Das DTO-Objekt kann genau dieselben Variablen wie die Entität enthalten, oder es können mehr oder weniger davon vorhanden sein. Wir erinnern uns, dass die Konvertierung eines Objekts in ein anderes eine Frage der Zuordnung ist. Im utils-Paket erstellen wir die MappingUtils-Klasse
package ru.java.rush.utils;

import org.springframework.stereotype.Service;
import ru.java.rush.dto.ProductDto;
import ru.java.rush.entities.ProductEntity;

@Service
public class MappingUtils {
//из entity в dto
    public ProductDto mapToProductDto(ProductEntity entity){
        ProductDto dto = new ProductDto();
        dto.setId(entity.getId());
        dto.setName(entity.getName());
        dto.setPurchasePrice(entity.getPurchasePrice());
        return dto;
    }
//из dto в entity
    public ProductEntity mapToProductEntity(ProductDto dto){
        ProductEntity entity = new ProductEntity();
        entity.setId(dto.getId());
        entity.setName(dto.getName());
        entity.setPurchasePrice(dto.getPurchasePrice());
        return entity;
    }
}
Wir füllen einfach die Felder eines Objekts mit ähnlichen Feldern eines anderen Objekts. In der ProductService-Klasse implementieren wir Methoden, um nach einem einzelnen Produkt oder einer Produktliste zu suchen. Zuvor konvertieren wir die Entität jedoch mithilfe der oben beschriebenen Methode in ein DTO.
private final ProductRepository productRepository;
private final MappingUtils mappingUtils;


//для листа продуктов мы использовали стрим
public List<ProductDto> findAll() {
    return productRepository.findAll().stream() //создали из листа стирим
            .map(mappingUtils::mapToProductDto) //оператором из streamAPI map, использовали для каждого Element метод mapToProductDto из класса MappingUtils
.collect(Collectors.toList()); //превратoder стрим обратно в коллекцию, а точнее в лист
}

//для одиночного продукта обошлись проще
public ProductDto findById(Integer id) {
    return mappingUtils.mapToProductDto( //в метод mapToProductDto
            productRepository.findById(id) //поместoder результат поиска по id
                    .orElse(new ProductEntity()) //если ни чего не нашли, то вернем пустой entity
    );
}
Was passiert, wenn wir dieses Gemüse jetzt zur Schau stellen? Mal sehen. Schreiben Sie dazu den folgenden Code in ItiiateUtil und führen Sie ihn aus.
System.out.println("\nВитрина магазина");
for (ProductDto dto : productService.findAll()) {
    System.out.println(dto);
}
Die Ausgabe lautet: Store display ProductDto(id=1, name=Kartoffeln, PurchasePrice=20, Verpackung=null, salePrice=null) ProductDto(id=2, name=Karotten, PurchasePrice=14, Verpackung=null, salePrice=null) Nun, Ich nicht! Niemand wird solches Gemüse kaufen: Es ist schmutzig, nicht verpackt und der Verkaufspreis ist unbekannt. Es ist Zeit für Geschäftslogik. Wir implementieren es in der ProductService-Klasse. Fügen wir dieser Klasse zunächst einige Variablen hinzu:
private final Integer margin = 5;//это наша накрутка на цену
private final String packaging = "Упаковано в лучшем виде";//так будет выглядеть упаковка
Für jede Aktion: Verpackung und Preisaufschlag erstellen wir eine separate Methode in derselben Klasse:
// упаковываем товар
public void pack(List<ProductDto> list) {
    list.forEach(productDto ->
            productDto.setPackaging(packaging)
    );
}

// делаем деньги
public void makeMoney(List<ProductDto> list) {
    list.forEach(productDto ->
            productDto.setSalePrice(productDto.getPurchasePrice() * margin)
    );
}
Wir kehren zu ItiiateUtil zurück und ersetzen die Anzeige auf dem Display durch den folgenden Code
List<ProductDto> productDtos = productService.findAll();

productService.pack(productDtos);
productService.makeMoney(productDtos);

System.out.println("\nВитрина магазина");
for (ProductDto dto : productDtos)) {
    System.out.println(dto);
}
Wir führen Folgendes durch: Store Display ProductDto(id=1, Name=Kartoffeln, Einkaufspreis=20, Verpackung=Bestmöglich verpackt, Verkaufspreis=100) ProductDto(id=2, Name=Karotten, Kaufpreis=14, Verpackung=Verpackt auf die bestmögliche Weise, salePrice=70) Das Produkt ist schön verpackt, es gibt einen Preis, aber haben Sie irgendwo auf dem Schaufenster den Preis gesehen, für den Sie es in großen Mengen gekauft haben, und eine andere ID? Wir ändern den oben geschriebenen Code mit einer Datei:
List<ProductDto> productDtos = productService.findAll();

productService.pack(productDtos);
productService.makeMoney(productDtos);

System.out.println("\nВитрина магазина");
for (ProductDto dto : productDtos) {
    System.out.println(String.format(
            "Купите: %s , по цене:  %d", dto.getName(), dto.getSalePrice()
    ));
}
Die Klasse InitiateUtils sollte letztendlich so aussehen:
@Service
@RequiredArgsConstructor
public class InitiateUtils implements CommandLineRunner {

    private final ProductService productService;

    @Override
    public void run(String... args) throws Exception {

        List<ProductEntity> products = new ArrayList<>(
                Arrays.asList(
                        new ProductEntity()
                                .setName("Картофель")
                                .setPurchasePrice(20),
                        new ProductEntity()
                                .setName("Морковь")
                                .setPurchasePrice(14)
                ));

        productService.saveAll(products);

        List<ProductDto> productDtos = productService.findAll();

        productService.pack(productDtos);
        productService.makeMoney(productDtos);

        System.out.println("\nВитрина магазина");
        for (ProductDto dto : productDtos) {
            System.out.println(String.format(
                    "Купите: %s , по цене:  %d", dto.getName(), dto.getSalePrice()
            ));
        }
    }
}
Los geht's: Schaufenster Kaufen: Kartoffeln, Preis: 100 Kaufen: Karotten, Preis: 70 Noch etwas! Jetzt glauben wir, dass dto gute Dinge gebracht hat, abgesehen von einer Menge zusätzlichem Code: 1. Wir können Geschäftslogik ausführen, ohne Objekte in der Datenbank zu ändern (sagen wir mal, wir brauchen keine Felder für Verpackung und Verkaufspreis). dieser Tisch). Auch ohne Verpackung mit Preisschild sind Kartoffeln gut lagerbar, dort sind sie sogar überflüssig. 2. In dieser Zeile List<ProductDto> productDtos = productService.findAll() haben wir einen Cache mit Objekten erstellt, mit denen innerhalb der Geschäftslogik bequem gearbeitet werden kann. Dies ist der Fall, wenn wir einen Teil der Waren in den Hinterraum des Ladens stellen. 3. Dadurch konnten wir zwei Geschäftsaktionen durchführen: Paketierung und Markup, aber wir stellten nur einmal eine Anfrage an die Datenbank (Abfragen an die Datenbank sind hinsichtlich der Leistung ziemlich schwierig). Sie können das Produkt verpacken, mit einem Preisschild versehen und ausstellen – indem Sie es nach und nach aus dem Hauswirtschaftsraum holen, anstatt ihm jedes Mal in den Lagerraum hinterherzurennen. Auf die Frage: „Warum ist das so schwierig?“ versucht man auch die Antwort zu finden, liest . Nächster Artikel
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION