每个实体的DTO对象

时间:2014-02-05 21:00:01

标签: java entity-framework design-patterns jpa dto

我继承了一个用Java编写的应用程序,它使用JPA来访问数据库。该应用程序使用了我之前未遇到的设计模式,我真的会对使用此模式的原因进行一些指导。像许多应用程序一样,我们有一个前端,中间件和后端数据库。通过DAO访问数据库。 DAO上的每个方法都加载一个实体-DTO,它只是一个POJO,只有getter和setter,然后实体-DTO被传递给一个实体本身,该实体具有改变实体状态的其他方法。一个例子[改变了类名以保护无辜者]

enum Gender
{
    Male,
    Female
}

class PersonDTO
{
    private String mFirstName;
    private String mLastName;
    private Gender mGender;
    ...

    String getFirstName() { return this.mFirstName; }
    String setFirstName(String name) { this.mFirstName = name; }
    // etc
}

class Person
{
    PersonDTO mDTO;
    Person(PersonDTO dto)
    {
        mDTO = dto;
    }

    String getFirstName() { return mDTO.getFirstName() }
    String setFirstName(String name) { mDTO.setFirstName(name); }
    // and so on

    void marry( Person aNotherPerson )
    {
        if( this.getGender()==Gender.Female && 
               aNotherPerson.getGender()==Gender.Male)
        {
            this.setLastName( aNotherPerson.getLastName() );
        }
        aNotherPerson.marry( this );
    }
}

这在30个左右的实体类中重复,使用DTO加倍到60,我只是无法理解为什么。我理解(比特)关于转换的分离,我也理解(比特)关于基于EAO的设计与基于活动记录的设计之间的区别。

但这真的要走这么远吗?应该总是至少有一个" DB"只包含映射到数据库字段的getter和setter的对象?

4 个答案:

答案 0 :(得分:1)

免责声明:对此主题有不同的意见,根据您的系统架构,您可能无法选择。

随着那个说...我已经看过这个模式之前实现过,而不是它的忠实粉丝,在我看来,重复大量代码而不增加任何实际价值。它似乎在使用像SOAP这样的XML API的系统中特别受欢迎,因为可能很难将XML结构直接映射到对象结构。在您的特定情况下,它似乎更糟糕,因为除了重复的getFirstName()/ getLastName()方法之外,还有业务逻辑(属于服务层)编码到pojo(应该是一个简单的数据传输对象)像DTO一样)。为什么pojo知道只有异性的人才能结婚?

为了更好地理解为什么,您能解释一下这些DTO的来源吗?是否有一个前端向控制器提交数据,然后将其转换为DTO,然后用于使用数据填充您的实体?

答案 1 :(得分:1)

它们也可能只是将JPA注释与富域对象分开使用。

所以我猜测有人不喜欢在一个类中使用JPA注释和丰富的域对象行为。有人可能也认为JPA注释和富域对象不应该在同一层(因为注释混合了关注点),所以如果你赢了这个论点,你会得到这种分离。

另一个你看到这种事情发生的地方是你想要从丰富的域对象中抽象出类似的注释(比如web服务中的jaxb注释)。

因此,意图可能是DTO作为从代码到数据库的序列化机制的一种,这与提到的here by martin fowler的意图非常相似。

答案 2 :(得分:0)

这似乎不是一个已知的模式。

一般

  • 通常维护一个单独的对象来表示数据库中的记录,称为域对象。
  • 对象上的CRUD操作是DAO类的一部分,其他业务操作将是Manager类的一部分,但这些类都不将域对象存储为成员变量,即DAO和Manager都不携带状态。它们只是处理作为参数传入的域对象的元素。
  • DTO用于前端和后端之间的通信,以便从DB呈现数据或接受来自最终用户的输入
  • DTO通过Manager类转换为Domain对象,其中根据业务规则执行验证和修改。这些域对象使用DAO类保存在DB中。

答案 3 :(得分:0)

我参与过一个项目,我们有一个DTO,其唯一目的是将信息从前端控制器传输到一些外观层。然后,外观层负责将这些DTO转换为域对象。

这种分层背后的想法是将前端(视图)与域分离。有时,DTO可以包含多个域对象以用于聚合视图。但是域层总是呈现干净,可重用,可缓存(如果需要)的对象。