JavaRush /Blog Java /Random-MS /Musim bunga tidak menakutkan, lapisan DTO

Musim bunga tidak menakutkan, lapisan DTO

Diterbitkan dalam kumpulan
KANDUNGAN KITARAN ARTIKEL Kami terus bercakap tentang Spring. Hari ini kita akan menganalisis corak DTO, untuk pemahaman anda boleh baca di sini . Perkara yang paling sukar tentang DTO ialah memahami mengapa ia diperlukan. Mari kita mula membuat spekulasi tentang sayur-sayuran, dan pada masa yang sama, tulis beberapa kod, mungkin sesuatu akan menjadi lebih jelas di sepanjang jalan. Buat projek spring-boot , sambungkan h2 dan Lombok . Cipta pakej: entiti, repositori, perkhidmatan, kegunaan. Dalam entiti, buat entiti Produk:
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;//закупочная цена

}
Laksanakan kelas ProducRepository, ProducService dan kelas ItiiateUtil ( sama dengan artikel sebelumnya ). Katakan kami membeli kentang pada harga borong 20 rubel sekilogram, dan lobak merah pada harga 14 rubel sekilogram. Kami akan meletakkan produk yang dibeli di dalam simpanan. Mari tambahkan rekod berikut pada pangkalan data: [Id =1, name= “Kentang”, purchasePrice = 20] [Id =2, name= “Lobak merah”, purchasePrice = 14] Sebagai spekulator yang baik, kita mesti menjual barangan kita secara menguntungkan, untuk ini, mari bungkus dengan cantik dan kami akan menaikkan harga. Iaitu, kami mempunyai sayur-sayuran yang kotor dan tidak menarik bertimbun-timbun, tetapi akan ada produk vegan premium yang bersih dari segmen mewah. Setuju, ini bukan lagi produk (objek) yang sama yang kami beli secara pukal. Untuk produk baharu, buat pakej dto dan di dalamnya kelas ProductDto
package ru.java.rush.dto;

import lombok.Data;

@Data
public class ProductDto {
    Integer id;
    String name;
    Integer purchasePrice;
    String  packaging;//упаковка
    Integer salePrice;//цена реализации
}
ProductDto mempunyai dua pembolehubah yang ProductEntity tidak: "pembungkusan" dan "harga jualan". Objek dto mungkin mengandungi pembolehubah yang sama seperti entiti, atau mungkin terdapat lebih atau kurang daripadanya. Kami ingat bahawa menukar satu objek kepada yang lain adalah masalah pemetaan. Dalam pakej utils kami akan mencipta kelas 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;
    }
}
Kami hanya mengisi medan dari satu objek dengan medan yang serupa dari objek lain. Dalam kelas ProductService kami melaksanakan kaedah untuk mencari produk tunggal atau senarai produk, tetapi sebelum itu kami menukar entiti kepada dto menggunakan kaedah yang ditulis di atas.
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
    );
}
Apakah yang akan berlaku jika kita meletakkan sayur-sayuran ini pada paparan? Jom tengok. Untuk melakukan ini, tulis kod berikut dalam ItiiateUtil dan jalankannya.
System.out.println("\nВитрина магазина");
for (ProductDto dto : productService.findAll()) {
    System.out.println(dto);
}
Outputnya ialah: Paparan kedai ProductDto(id=1, name=Kentang, purchasePrice=20, packaging=null, salePrice=null) ProductDto(id=2, name=Lobak merah, purchasePrice=14, packaging=null, salePrice=null) Nah, saya tidak! Tiada siapa yang akan membeli sayur-sayuran seperti itu: ia kotor, tidak dibungkus, dan harga jualan tidak diketahui. Sudah tiba masanya untuk logik perniagaan. Kami melaksanakannya dalam kelas ProductService. Mari kita tambahkan beberapa pembolehubah pada kelas ini dahulu:
private final Integer margin = 5;//это наша накрутка на цену
private final String packaging = "Упаковано в лучшем виде";//так будет выглядеть упаковка
Untuk setiap tindakan: pembungkusan dan penanda harga, kami akan mencipta kaedah berasingan dalam kelas yang sama:
// упаковываем товар
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)
    );
}
Kami kembali ke ItiiateUtil dan menggantikan paparan pada paparan dengan kod berikut
List<ProductDto> productDtos = productService.findAll();

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

System.out.println("\nВитрина магазина");
for (ProductDto dto : productDtos)) {
    System.out.println(dto);
}
Kami menjalankan: Paparan kedai ProductDto(id=1, nama=Kentang, harga pembelian=20, pembungkusan=Dibungkus dengan cara yang terbaik, harga jualan=100) ProdukDto(id=2, nama=Lobak merah, harga pembelian=14, pembungkusan=Dibungkus dengan cara yang terbaik, salePrice=70) Produk dibungkus dengan cantik, ada harga, tetapi pernahkah anda melihat di suatu tempat di tingkap memaparkan harga yang anda beli secara pukal dan beberapa id lain. Kami mengubah suai kod yang ditulis di atas dengan fail:
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()
    ));
}
class InitiateUtils akhirnya akan kelihatan seperti ini:
@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()
            ));
        }
    }
}
Mari lancarkan: Tetingkap kedai Beli: Kentang, harga: 100 Beli: Lobak merah, harga: 70 Perkara lain! Sekarang kita berfikir bahawa dto membawa perkara yang baik, kecuali sekumpulan kod tambahan: 1. Kita boleh melakukan logik perniagaan tanpa mengubah objek dalam pangkalan data (katakan, kita tidak perlu mempunyai medan tentang pembungkusan dan harga jualan dalam jadual ini). Kentang akan bertahan dengan baik dalam simpanan walaupun tanpa pembungkusan dengan tanda harga, malah ia berlebihan di sana. 2. Dalam baris ini List<ProductDto> productDtos = productService.findAll() kami mencipta cache objek yang mudah digunakan dalam logik perniagaan. Ini adalah jika kita meletakkan beberapa barang di ruang belakang kedai. 3. Ini membolehkan kami melakukan dua tindakan perniagaan: pembungkusan dan penandaan, tetapi kami membuat permintaan kepada pangkalan data sekali sahaja (pertanyaan kepada pangkalan data agak sukar dari segi prestasi). Anda boleh membungkus produk, meletakkan tanda harga padanya dan meletakkannya pada paparan - secara beransur-ansur mengambilnya dari bilik utiliti, dan bukannya mengejarnya setiap kali ke bilik simpanan. Kepada soalan: "Mengapa ia begitu sukar?", orang juga cuba mencari jawapannya, baca . Artikel seterusnya
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION