JavaRush /Java Blog /Random-IT /La primavera non fa paura, uno strato DTO
Павел
Livello 11

La primavera non fa paura, uno strato DTO

Pubblicato nel gruppo Random-IT
CONTENUTI DEL CICLO DI ARTICOLI Continuiamo a parlare di Primavera. Oggi analizzeremo il pattern DTO, per capirlo potete leggere qui . La cosa più difficile del DTO è capire perché è necessario. Cominciamo a speculare sulle verdure e, allo stesso tempo, scriviamo del codice, forse qualcosa diventerà più chiaro lungo la strada. Crea un progetto spring-boot , collega h2 e Lombok . Crea pacchetti: entità, repository, servizi, utilità. Nelle entità, crea un'entità Prodotto:
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;//закупочная цена

}
Implementa le classi ProducRepository, ProducService e la classe ItiiateUtil ( simile all'articolo precedente ). Diciamo che abbiamo acquistato le patate al prezzo all'ingrosso di 20 rubli al kg e le carote a 14 rubli al kg. Metteremo in giacenza i prodotti acquistati. Aggiungiamo i seguenti record al database: [Id =1, nome= “Patate”, prezzoacquisto = 20] [Id =2, nome= “Carote”, prezzoacquisto = 14] Come speculatori decenti, dobbiamo vendere con profitto i nostri beni, per questo confezioniamolo bene e aumentiamo il prezzo. Cioè, avevamo verdure sporche e poco attraenti ammucchiate in un mucchio, ma ci saranno prodotti vegani premium puliti del segmento del lusso. D'accordo, questo non sarà più lo stesso prodotto (oggetto) che abbiamo acquistato sfuso. Per un nuovo prodotto, crea un pacchetto dto e al suo interno la classe ProductDto
package ru.java.rush.dto;

import lombok.Data;

@Data
public class ProductDto {
    Integer id;
    String name;
    Integer purchasePrice;
    String  packaging;//упаковка
    Integer salePrice;//цена реализации
}
ProductDto ha due variabili che ProductEntity non ha: "confezione" e "prezzo di vendita". L'oggetto dto può contenere esattamente le stesse variabili dell'entità, oppure potrebbero essercene più o meno. Ricordiamo che convertire un oggetto in un altro è una questione di mappatura. Nel pacchetto utils creeremo la classe MappingUtils
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;
    }
}
Compiliamo semplicemente i campi di un oggetto con campi simili di un altro oggetto. Nella classe ProductService implementiamo metodi per cercare un singolo prodotto o una lista di prodotti, ma prima convertiamo l'entità in un dto utilizzando il metodo scritto sopra.
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()); //превратor стрим обратно в коллекцию, а точнее в лист
}

//для одиночного продукта обошлись проще
public ProductDto findById(Integer id) {
    return mappingUtils.mapToProductDto( //в метод mapToProductDto
            productRepository.findById(id) //поместor результат поиска по id
                    .orElse(new ProductEntity()) //если ни чего не нашли, то вернем пустой entity
    );
}
Cosa accadrebbe se ora mettessimo queste verdure in mostra? Vediamo. Per fare ciò, scrivi il seguente codice in ItiiateUtil ed eseguilo.
System.out.println("\nВитрина магазина");
for (ProductDto dto : productService.findAll()) {
    System.out.println(dto);
}
L'output è: Store display ProductDto(id=1, name=Potatoes, PurchasePrice=20, packaging=null, salePrice=null) ProductDto(id=2, name=Carrots, PurchasePrice=14, packaging=null, salePrice=null) Bene io no! Nessuno comprerà queste verdure: sono sporche, non confezionate e il prezzo di vendita non è noto. È il momento della logica aziendale. Lo implementiamo nella classe ProductService. Aggiungiamo prima un paio di variabili a questa classe:
private final Integer margin = 5;//это наша накрутка на цену
private final String packaging = "Упаковано в лучшем виде";//так будет выглядеть упаковка
Per ogni azione: confezionamento e ricarico del prezzo, creeremo un metodo separato nella stessa classe:
// упаковываем товар
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)
    );
}
Torniamo a ItiiateUtil e sostituiamo la visualizzazione sul display con il seguente codice
List<ProductDto> productDtos = productService.findAll();

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

System.out.println("\nВитрина магазина");
for (ProductDto dto : productDtos)) {
    System.out.println(dto);
}
Effettuiamo: Visualizzazione del negozio ProductDto(id=1, name=Potatoes, PurchasePrice=20, packaging=Packed in the best possible, salePrice=100) ProductDto(id=2, name=Carrots, PurchasePrice=14, packaging=Packed nel miglior modo possibile, salePrice=70) Il prodotto è ben confezionato, c'è un prezzo, ma hai visto da qualche parte sulla vetrina il prezzo per il quale lo hai acquistato in blocco e qualche altro ID. Modifichiamo il codice scritto sopra con un file:
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()
    ));
}
la classe InitiateUtils alla fine dovrebbe assomigliare a questa:
@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()
            ));
        }
    }
}
Lanciamo: Vetrina Acquista: Patate, prezzo: 100 Acquista: Carote, prezzo: 70 Un'altra cosa! Ora pensiamo che dto abbia portato cose positive, ad eccezione di un mucchio di codice aggiuntivo: 1. Possiamo eseguire la logica aziendale senza modificare gli oggetti nel database (diciamo, beh, non abbiamo bisogno di avere campi sull'imballaggio e sul prezzo di vendita in questo tavolo). Le patate dureranno bene in magazzino anche senza imballaggio con cartellino del prezzo, lì sono addirittura superflue. 2. In questa riga List<ProductDto> productDtos = productService.findAll() abbiamo creato una cache di oggetti con cui è conveniente lavorare all'interno della logica aziendale. Questo è se mettiamo parte della merce nel retro del negozio. 3. Ciò ci ha permesso di eseguire due azioni aziendali: packaging e markup, ma abbiamo effettuato una richiesta al database solo una volta (le query al database sono piuttosto difficili in termini di prestazioni). Puoi imballare il prodotto, metterci sopra un cartellino del prezzo e metterlo in mostra, ritirandolo gradualmente dal ripostiglio, invece di rincorrerlo ogni volta nel magazzino. Alla domanda: "Perché è così difficile?", le persone cercano anche di trovare la risposta, leggi . Articolo successivo
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION