java - 将数据从表单对象传输到实体以进行更新方法的更干净的方法是什么?

标签 java spring spring-mvc spring-boot

尝试重构以下 Controller 的代码:

 @PutMapping("products/{productId}")
    public ProductResponse updateProduct(@PathVariable("productId") Long productId, @RequestBody ProductForm productForm) {
        Optional<Product> foundProductOpt = productRepository.findById(productId);
        Product foundProduct = foundProductOpt.orElseThrow(() -> new EntityNotFoundException("productId" + productId + "not found."));

        //would like to refactor code below!!

        foundProduct.setProductTitle(productForm.getProductTitle());
        foundProduct.setProductPrice(productForm.getProductPrice());
        foundProduct.setProductDescription(productForm.getProductDescription());
        foundProduct.setProductImage(productForm.getProductImage());
        productRepository.save(foundProduct);

        return new ProductResponse(null, "product updated");
    }

我只是将值从表单对象传输到实体对象。想过创建一个方法,但不想在实体中编写方法,因此不确定还有哪些其他解决方案。

根据请求,下面是我的产品和表单对象。我想使用表单对象进行验证,然后将数据传输到 Product 对象。

产品.java

package com.assignment.restapi.domain;

import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.Min;
import java.util.Date;

@Entity
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long productId;
    private String productImage;
    private String productTitle;
    private String productDescription;
    private Integer productPrice;
    //https://stackoverflow.com/questions/49954812/how-can-you-make-a-created-at-column-generate-the-creation-date-time-automatical/49954965#49954965
    @CreationTimestamp
    private Date createdAt;
    @UpdateTimestamp
    private Date updatedAt;

    // default constructor
    public Product() {

    }
    // parameterized constructor-User enetered value goes here to set the fields of the instantiated object.
    public Product(String productImage, String productTitle, String productDescription, Integer productPrice, Date createdAt) {
        this.productImage = productImage;
        this.productTitle = productTitle;
        this.productDescription = productDescription;
        this.productPrice = productPrice;
        this.createdAt = createdAt;
    }
    // getter methods are used to retrieve a value from an object.
    // setter methods are used to set a new value to an object.
    public Long getProductId() {
        return productId;
    }

    public void setProductId(Long productId) {
        this.productId = productId;
    }

    public String getProductImage() {
        return productImage;
    }

    public void setProductImage(String productImage) {
        this.productImage = productImage;
    }

    public String getProductTitle() {
        return productTitle;
    }

    public void setProductTitle(String productTitle) {
        this.productTitle = productTitle;
    }

    public String getProductDescription() {
        return productDescription;
    }

    public void setProductDescription(String productDescription) {
        this.productDescription = productDescription;
    }

    public Integer getProductPrice() {
        return productPrice;
    }

    public void setProductPrice(@Min(value = 1, message = "値段は0以上の値を設定してください。") Integer productPrice) {
        this.productPrice = productPrice;
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }

    public Date getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(Date updatedAt) {
        this.updatedAt = updatedAt;
    }
}

产品表单.java

package com.assignment.restapi.web.view;

import com.assignment.restapi.domain.Product;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;

public class ProductForm {

    String productImage;

    @NotBlank(message = "Product title is necessary")
    @Size(max = 100, message = "Product title has to be less than 100 letters")
    String productTitle;

    @Size(max = 500, message = "Product title has to be less than 500 letters")
    String productDescription;

    @Min(value = 1, message = "price has to have a value larger than 1")
    Integer productPrice;

    public ProductForm() {

    }

    public ProductForm(String productImage, String productTitle, String productDescription, Integer productPrice) {
        this.productImage = productImage;
        this.productTitle = productTitle;
        this.productDescription = productDescription;
        this.productPrice = productPrice;
    }

    public String getProductImage() {
        return productImage;
    }

    public void setProductImage(String productImage) {
        this.productImage = productImage;
    }

    public String getProductTitle() {
        return productTitle;
    }

    public void setProductTitle(String productTitle) {
        this.productTitle = productTitle;
    }

    public String getProductDescription() {
        return productDescription;
    }

    public void setProductDescription(String productDescription) {
        this.productDescription = productDescription;
    }

    public Integer getProductPrice() {
        return productPrice;
    }

    public void setProductPrice(Integer productPrice) {
        this.productPrice = productPrice;
    }

    //turns productForm into Product object.
    public Product convertToProduct() {
        //step by step debug mode, new object constructor function in Product.java gets called.
        //setter methods get called and values of the ProductForm object gets passed and becomes the new value of the Product object.
        Product product = new Product();
        product.setProductTitle(this.productTitle);
        product.setProductImage(this.productImage);
        product.setProductDescription(this.productDescription);
        product.setProductPrice(this.productPrice);
        return product;
    }
}

最佳答案

使用 Apache commons-beanutils::

如果两个类中具有相同的字段名称,这将起作用。

@PutMapping("products/{productId}")
public ProductResponse updateProduct(@PathVariable("productId") Long productId, @RequestBody ProductForm productForm) {
    Optional<Product> foundProductOpt = productRepository.findById(productId);
    Product foundProduct = foundProductOpt.orElseThrow(() -> new EntityNotFoundException("productId" + productId + "not found."));
    org.apache.commons.beanutils.BeanUtils.copyProperties(foundProduct, productForm); 
    productRepository.save(foundProduct);
    return new ProductResponse(null, "product updated");
}

关于java - 将数据从表单对象传输到实体以进行更新方法的更干净的方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49955529/

相关文章:

java - 从jvm字节码生成java类文件头

java - Java 中的当前日期时间,使用 mySQL 类型日期时间格式的 Joda 时间

java - 字节[]到位图与位图到字节[] : Which is Faster?

Spring Cloud 发现多个服务版本

spring - 如何删除/隐藏 Atomikos 启动错误消息?

java - 自定义 Spring Security OAuth 2 响应

web-applications - 我的应用程序无法打开ServletContext资源

java - ClassFormatError : 154>, Display 类中捕获异常

java - 我应该如何验证 Spring Rest API 中 @requestparam 中的依赖参数?

java - Spring MVC 在调用 SpringStoredProcedure.execute() 后是否发出提交