JavaRush /จาวาบล็อก /Random-TH /ฤดูใบไม้ผลิไม่น่ากลัว เป็นชั้น DTO
Павел
ระดับ

ฤดูใบไม้ผลิไม่น่ากลัว เป็นชั้น DTO

เผยแพร่ในกลุ่ม
เนื้อหาของวงจรบทความ เรายังคงพูดคุยเกี่ยวกับฤดูใบไม้ผลิต่อไป วันนี้เราจะวิเคราะห์รูปแบบ DTO เพื่อความเข้าใจคุณสามารถอ่านได้ที่นี่ สิ่งที่ยากที่สุดเกี่ยวกับ DTO คือการทำความเข้าใจว่าทำไมจึงจำเป็น มาเริ่มคาดเดาเกี่ยวกับผักกันดีกว่าและในขณะเดียวกันก็เขียนโค้ดบางทีอาจมีบางอย่างชัดเจนขึ้นระหว่างทาง สร้างโครงการ spring-bootเชื่อมต่อ h2 และ Lombok สร้างแพ็คเกจ: เอนทิตี พื้นที่เก็บข้อมูล บริการ และยูทิลิตี้ ในเอนทิตี สร้างเอนทิตีผลิตภัณฑ์:
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;//закупочная цена

}
ใช้คลาส ProducRepository, ProducService และคลาส ItiiateUtil ( คล้ายกับบทความก่อนหน้า ) สมมติว่าเราซื้อมันฝรั่งในราคาขายส่ง 20 รูเบิลต่อกิโลกรัม และแครอทในราคา 14 รูเบิลต่อกิโลกรัม เราจะนำผลิตภัณฑ์ที่ซื้อไปจัดเก็บ มาเพิ่มบันทึกต่อไปนี้ลงในฐานข้อมูล: [Id =1, name= “Potatoes”, buyPrice = 20] [Id =2, name= “Carrots”, buyPrice = 14] ในฐานะนักเก็งกำไรที่ดี เราต้องขายสินค้าของเราอย่างมีกำไร เรามาแพ็คให้สวยงามกันเถอะ แล้วเราจะขึ้นราคาให้ นั่นคือเรามีผักที่สกปรกและไม่สวยกองรวมกันเป็นกอง แต่จะมีผลิตภัณฑ์วีแก้นระดับพรีเมียมที่สะอาดจากกลุ่มสินค้าฟุ่มเฟือย ยอมรับว่านี่จะไม่ใช่ผลิตภัณฑ์ (วัตถุ) แบบเดียวกับที่เราซื้อจำนวนมากอีกต่อไป สำหรับผลิตภัณฑ์ใหม่ มาสร้างแพ็คเกจ dto และคลาส ProductDto ในนั้น
package ru.java.rush.dto;

import lombok.Data;

@Data
public class ProductDto {
    Integer id;
    String name;
    Integer purchasePrice;
    String  packaging;//упаковка
    Integer salePrice;//цена реализации
}
ProductDto มีตัวแปรสองตัวที่ ProductEntity ไม่มี: “บรรจุภัณฑ์” และ “ราคาขาย” วัตถุ dto อาจมีตัวแปรเหมือนกับเอนทิตีทุกประการ หรืออาจมีมากหรือน้อยกว่าก็ได้ เราจำได้ว่าการแปลงวัตถุหนึ่งไปเป็นอีกวัตถุหนึ่งนั้นเป็นเรื่องของการทำแผนที่ ในแพ็คเกจ utils เราจะสร้างคลาส 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;
    }
}
เราเพียงแค่กรอกข้อมูลในฟิลด์จากวัตถุหนึ่งด้วยฟิลด์ที่คล้ายกันจากอีกวัตถุหนึ่ง ในคลาส ProductService เราใช้วิธีการค้นหาผลิตภัณฑ์เดียวหรือรายการผลิตภัณฑ์ แต่ก่อนหน้านั้น เราแปลงเอนทิตีเป็น 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()); //превратor стрим обратно в коллекцию, а точнее в лист
}

//для одиночного продукта обошлись проще
public ProductDto findById(Integer id) {
    return mappingUtils.mapToProductDto( //в метод mapToProductDto
            productRepository.findById(id) //поместor результат поиска по id
                    .orElse(new ProductEntity()) //если ни чего не нашли, то вернем пустой entity
    );
}
จะเกิดอะไรขึ้นถ้าเรานำผักเหล่านี้มาตั้งโชว์? มาดูกัน. เมื่อต้องการทำเช่นนี้ ให้เขียนโค้ดต่อไปนี้ใน ItiiateUtil และเรียกใช้
System.out.println("\nВитрина магазина");
for (ProductDto dto : productService.findAll()) {
    System.out.println(dto);
}
ผลลัพธ์คือ: Store display ProductDto(id=1, name=Potatoes, buyPrice=20, packaging=null, salePrice=null) ProductDto(id=2, name=Carrots, buyPrice=14, packaging=null, salePrice=null) ฉันไม่ทำ! จะไม่มีใครซื้อผักประเภทนี้ พวกมันสกปรก ไม่ได้บรรจุหีบห่อ และไม่ทราบราคาขาย ถึงเวลาสำหรับตรรกะทางธุรกิจแล้ว เรานำไปใช้ในคลาส ProductService ก่อนอื่นเรามาเพิ่มตัวแปรสองสามตัวให้กับคลาสนี้:
private final Integer margin = 5;//это наша накрутка на цену
private final String packaging = "Упаковано в лучшем виде";//так будет выглядеть упаковка
สำหรับแต่ละการกระทำ: การบรรจุหีบห่อและการมาร์กอัปราคา เราจะสร้างวิธีการแยกกันในระดับเดียวกัน:
// упаковываем товар
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)
    );
}
เรากลับไปที่ ItiiateUtil และแทนที่จอแสดงผลบนจอแสดงผลด้วยรหัสต่อไปนี้
List<ProductDto> productDtos = productService.findAll();

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

System.out.println("\nВитрина магазина");
for (ProductDto dto : productDtos)) {
    System.out.println(dto);
}
เราดำเนินการ: จัดเก็บผลิตภัณฑ์ที่แสดง ProductDto(id=1, name=Potatoes, buyPrice=20, packaging=Packed in the best way possible, salePrice=100) ProductDto(id=2, name=Carrots, buyPrice=14, packaging=Packed ในวิธีที่ดีที่สุดที่เป็นไปได้ salePrice=70) สินค้าได้รับการบรรจุหีบห่ออย่างสวยงาม มีราคา แต่คุณเคยเห็นที่ไหนสักแห่งบนหน้าต่างที่แสดงราคาที่คุณซื้อจำนวนมากและรหัสอื่นๆ เราแก้ไขโค้ดที่เขียนด้านบนด้วยไฟล์:
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()
    ));
}
ในที่สุดคลาส InitiateUtils ควรมีลักษณะเช่นนี้:
@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()
            ));
        }
    }
}
เปิดตัว: หน้าต่างร้านค้า ซื้อ: มันฝรั่ง ราคา: 100 ซื้อ: แครอท ราคา: 70 อีกอย่าง! ตอนนี้เราคิดว่าจะนำสิ่งดีๆ มาให้ ยกเว้นโค้ดเพิ่มเติมจำนวนหนึ่ง: 1. เราสามารถดำเนินตรรกะทางธุรกิจได้โดยไม่ต้องเปลี่ยนออบเจ็กต์ในฐานข้อมูล (สมมติว่า เราไม่จำเป็นต้องมีฟิลด์เกี่ยวกับบรรจุภัณฑ์และราคาขายใน ตารางนี้) มันฝรั่งจะคงอยู่ได้ดีในการจัดเก็บแม้ว่าจะไม่มีบรรจุภัณฑ์ที่มีป้ายราคาก็ตาม แต่มันก็ไม่จำเป็นด้วยซ้ำ 2. ในบรรทัดนี้List<ProductDto> productDtos = productService.findAll()เราได้สร้างแคชของออบเจ็กต์ที่สะดวกในการทำงานด้วยภายในตรรกะทางธุรกิจ นี่คือถ้าเราวางสินค้าบางส่วนไว้ที่ห้องด้านหลังของร้าน 3. สิ่งนี้ทำให้เราสามารถดำเนินการทางธุรกิจได้สองอย่าง: การบรรจุหีบห่อและมาร์กอัป แต่เราได้ส่งคำขอไปยังฐานข้อมูลเพียงครั้งเดียว (การสืบค้นไปยังฐานข้อมูลนั้นค่อนข้างยากในแง่ของประสิทธิภาพ) คุณสามารถบรรจุผลิตภัณฑ์ ติดป้ายราคา และวางไว้บนจอแสดงผล โดยค่อยๆ หยิบสินค้าจากห้องเอนกประสงค์ แทนที่จะวิ่งตามทุกครั้งไปยังห้องเก็บของ สำหรับคำถาม: “ทำไมมันยากจัง” ผู้คนก็พยายามค้นหาคำตอบอ่าน . บทความถัดไป
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION