JavaRush /مدونة جافا /Random-AR /الربيع ليس مخيفًا، طبقة 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 روبلًا للكيلوغرام الواحد. سنقوم بتخزين المنتجات المشتراة. دعونا نضيف السجلات التالية إلى قاعدة البيانات: [المعرف = 1، الاسم = "البطاطس"، buyPrice = 20] [المعرف = 2، الاسم = "الجزر"، 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 على نفس المتغيرات تمامًا مثل الكيان، أو قد يكون هناك أكثر أو أقل منها. نتذكر أن تحويل كائن إلى آخر هو مسألة رسم الخرائط. في حزمة الأدوات سوف نقوم بإنشاء فئة 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);
}
الإخراج هو: عرض المتجر 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=بطاطس، سعر الشراء=20، التغليف=معبأة بأفضل طريقة ممكنة، سعر البيع=100) ProductDto(id=2، الاسم=جزر، سعر الشراء=14، التغليف=معبأة بأفضل طريقة ممكنة، 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 شيء آخر! الآن نعتقد أن dto جلب أشياء جيدة، باستثناء مجموعة من التعليمات البرمجية الإضافية: 1. يمكننا تنفيذ منطق الأعمال دون تغيير الكائنات في قاعدة البيانات (دعنا نقول، حسنًا، لا نحتاج إلى حقول حول التغليف وسعر البيع في هذه الطاولة). ستستمر البطاطس جيدًا في التخزين حتى بدون تغليفها ببطاقة سعر، بل إنها غير ضرورية هناك. 2. في هذا السطر List<ProductDto> ProductDtos = ProductService.findAll() قمنا بإنشاء ذاكرة تخزين مؤقت للكائنات الملائمة للعمل بها ضمن منطق الأعمال. هذا إذا وضعنا بعض البضائع في الغرفة الخلفية للمتجر. 3. سمح لنا هذا بتنفيذ إجراءين تجاريين: التعبئة والتغليف والترميز، لكننا قدمنا ​​طلبًا إلى قاعدة البيانات مرة واحدة فقط (الاستعلامات إلى قاعدة البيانات صعبة للغاية من حيث الأداء). يمكنك تعبئة المنتج ووضع بطاقة السعر عليه وعرضه - واستلامه تدريجيًا من غرفة المرافق، بدلاً من الركض خلفه في كل مرة إلى غرفة التخزين. على السؤال: "لماذا هو صعب للغاية؟" يحاول الناس أيضًا العثور على الإجابة، اقرأ . المقالة التالية
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION