何时需要使用DTO层?

4
我正在使用AngularJS作为前端和Java Play Framework作为后端服务开发Web应用程序。对于数据库访问,我使用Hibernate
到目前为止,我有大约30个服务来消费和生成JSON,我直接发送Hibernate对象而不是使用数据传输层。
目前我面临递归调用问题,因为Hibernate实体的双向引用。通过一些注释和JSON视图已经解决了这些问题,但是为不同的服务方法配置这些视图成为一个真正的问题,并且为JSON转换相应地注释实体会使实体对象变得臃肿。
目前我考虑使用DTO层来简化通信,但我不确定为每个服务准备请求和响应DTO对象所带来的开发和性能开销是否值得。这是一个好主意吗?

与主要影响性能的因素(如网络延迟和数据库访问)相比,DTO的开销可以忽略不计。 - Kayaman
我能猜到,但我的想法是指开发每个服务时需要反复花费的开销。 - Seyf
数据传输对象(Data Transfer Objects)在需要保护不同模型表示的数据的更改时非常有益。例如,在数据对象和业务对象之间。如果您注意到业务对象经常更改,但数据部分保持不变,例如使用DTO将非常有用。系统的不同层将与表示相同数据的不同模型进行交互。 - whitecoffee
3个回答

1

DTO将使用与实体对象相同的字符串池。如果您的实体中有复杂的对象,您可以在DTO和实体之间进行浅拷贝。

使用DTO将保护服务层方法不暴露实体设计。使用DTO不应导致显著的性能问题。


0

我采用编写XSD模式定义DTO对象的方法,然后使用插件生成实际的POJOs。在我的entities中,我添加了toEntityTypefromEntityType翻译方法。这将DTO翻译直接耦合到实体和控制服务中。我不需要编写POJOs,而XSD作为文档。例如,一个实体。

public class Product {
    private Long id;
    private String name;

    /**
     * Fill out properties from PurchaseOrderType. Copies all dependencies.   
     * @param productType {@link ProductType}
     * @return Product
     */
    public Product fromProductType(ProductType productType) {
        this.id = productType.getId();
        this.name = productType.getName();
        return this;
    }

    /**
     * Create and return ProductType representation. 
     * @return {@link ProductType}
     */
    public ProductType asProductType() {
        ProductType productType = new ProductType(); 
        productType.setId(id);
        productType.setName(name);
        return productType;
    }
    ... getters, setters, 
}

一个XSD定义:
<!-- product -->
<xsd:element name="productType">
    <xsd:complexType>
        <xsd:sequence>
            <xsd:element name="id" type="xsd:long" minOccurs="0"/>
            <xsd:element name="name" type="xsd:string" />
        </xsd:sequence>
    </xsd:complexType>
</xsd:element>

在pom.xml文件中
        <plugin>
            <groupId>org.jvnet.jaxb2.maven2</groupId>
            <artifactId>maven-jaxb2-plugin</artifactId>
            <version>0.13.2</version>
            <executions>
                <execution>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

以及一个服务

/**
 * Rest endpoint for a ProductType
 * rest/productservice/getproduct/{id}
 * @param id @{link Long}
 * @return {@link ProductType}
 */
@GET
@Path("getproduct/{id}")
@Produces({MediaType.APPLICATION_JSON})
public ProductType getProduct(@PathParam("id") Long id) throws Exception {
    // retrieve product information based on the id supplied in the formal argument
    Product getProduct = productDao.getProduct(id);
    if ( getProduct == null )
        throw new IllegalArgumentException("Product not found for id: " + id);
    ProductType productType = getProduct.asProductType();
    return productType;
}

0

实际上,您甚至可以通过使用DTO方法来提高性能,因为您可以查询更少的数据,假设DTO不是您实体模型的1:1副本。 我写了一篇文章,介绍了使用实体模型时遇到的问题以及如何使用Blaze-Persistence Entity Views有效地实现DTO方法。也许您想尝试一下,看看它如何改善您的设计和性能!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接