JavaRush /Java Blog /Random-JA /春は怖くない、DTO レイヤー
Павел
レベル 11

春は怖くない、DTO レイヤー

Random-JA グループに公開済み
記事サイクルの内容 引き続き春について話します。今日は DTO パターンを分析します。理解するには、ここを参照してください。DTO について最も難しいのは、DTO が必要な理由を理解することです。野菜について推測を始めて、同時にコードを書いてみましょう。途中で何かが明らかになるかもしれません。spring-boot プロジェクトを作成し、 h2Lombokを接続します。パッケージを作成します: エンティティ、リポジトリ、サービス、ユーティリティ。エンティティで、Product エンティティを作成します。
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 クラスを実装します (前の記事と同様)。卸売価格でジャガイモを1kgあたり20ルーブル、ニンジンを1kgあたり14ルーブルで購入したとします。ご購入いただいた商品はお預かりさせていただきます。次のレコードをデータベースに追加しましょう: [Id = 1, name= “ジャガイモ”, PurchasePrice = 20] [Id = 2, name= “ニンジン”, PurchasePrice = 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 にはない 2 つの変数、「パッケージング」と「販売価格」があります。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);
}
出力は次のようになります。 ストア 表示 ProductDto(id=1, name=Potatoes, PurchasePrice=20,Packaging=null, salePrice=null) ProductDto(id=2, name=キャロット, PurchasePrice=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=じゃがいも, PurchasePrice=20, 包装=最良の方法で梱包, salePrice=100) ProductDto(id=2, name=にんじん, PurchasePrice=14, 包装=梱包済み)を実行し ます。最善の方法で、salePrice=70) 製品は美しく梱包されており、価格が記載されていますが、ウィンドウのどこかに、一括購入した価格とその他の ID が表示されているのを見たことがありますか。上記のコードをファイルで変更します。
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 つ! 一連の追加コードを除いて、dto は良いことをもたらしたと考えています。 1. データベース内のオブジェクトを変更せずにビジネス ロジックを実行できます (たとえば、パッケージや販売価格に関するフィールドは必要ありません)。この表)。ジャガイモは、値札付きの包装をしなくても、保存に十分に耐えます。2. この行List<ProductDto> productDtos = productService.findAll()では、ビジネス ロジック内での操作に便利なオブジェクトのキャッシュを作成しました。これは、商品の一部を店舗の奥の部屋に置いた場合です。3. これにより、パッケージ化とマークアップという 2 つのビジネス アクションを実行できるようになりましたが、データベースへのリクエストは 1 回だけでした (データベースへのクエリはパフォーマンスの点で非常に困難です)。製品を梱包し、値札を付けて陳列することで、毎回保管室まで追いかけるのではなく、ユーティリティルームから徐々に製品を拾うことができます。「なぜそれはそんなに難しいのですか?」という質問に対して、人々はまた、を読んで答えを見つけようとします。 次の記事
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION