数据传输对象、数据访问对象或服务层?

5
我的应用程序基于典型的3层体系结构,目标是创建一个SpringMVC网站和一个Spring Batch解决方案,用于提供和维护我们数据库中的产品和库存,其中速度是非常重要的因素。
我正在使用Spring的JdbcTemplate来管理遗留数据库。我的一些表包含许多我不使用的列,并且检索整个行已显示出负面影响,因为某些字段的大小(我们甚至不需要映射的blob),因此我创建了一些匹配我想要检索的列的bean,例如:
- Product -- 包含与DB中存储的字段的1:1关系。 - ProductDetailsView -- 包含id、name、price、description、stock。 - ProductListItemView -- Id、Price、name、stock。
DAO层将这些bean返回给服务层。据我所知,为Product创建DTO在服务接口中公开它可能有意义,但是,
1. 那么ProductDetailsView和ProductListItemView呢? 2. 我应该从这些'views'或'projections'中进行1:1映射到具有相同属性的DTO吗?为什么? 3. 在任何情况下,您会在哪里放置JSR-303注释以验证网络输入?
1个回答

2
通常使用DTO是为了将实体与视图解耦,因此数据库内部的任何更改都不会影响视图或客户端,并且视图根本不需要更改。除非您需要发送更多或不同的信息。但是,您没有使用JPA,而是使用jdbctemplate,因此您的对象可以立即作为DTO,因为您不会受到数据库模型的限制。
对于Product实体,创建DTO似乎是一个好方法,因为您的视图对象仅是存储在数据库中的整个对象的部分表示。
  1. 我看到ProductDetailsView和ProductListItemView中的列数量很少(可能只设置了一组),如果您认为表定义不会有太多变化,因为它们不是很大,您可以像使用rest repository方式一样使用实体对象。
  2. 投影是解决相同要求的不同方法,避免发送对视图无关的信息,但这将在同一个POJO中包含jackson注释和jpa注释。(这更多是在使用ORM时)人们不太喜欢这样,这就是为什么创建DTO的方式
  3. 通常JSR303注释属于“输入”对象,它们在到达控制器时立即进行检查,您可以使用与springmvc和jsr非常配合的@Validated注释,这用于属于您端点的方法。
我认为没有黄金规则,但我会尽量将视图与数据库层解耦。因为您正在使用jdbcTemplate,所以您无需担心带来整个表示或在表的急切/懒惰集合方面出现问题,因为您始终可以修改投影以获取将要使用的内容。考虑从DAO中获取DTO,您将发送到视图并在CRUD操作中使用相同的DTO作为输入对象。

1
你好,感谢您提供非常有用的答案,非常感激。如果我们在服务层需要特定的DTO(假设我们需要在实体的这些缩小版本中添加一些在服务层计算的字段),但是我们在DAO中使用了检索到的结果作为即时DTO,那么我们应该把这两种类型的DTO放在哪里,如何命名呢?下面是我现在能想到的一些例子:org.company.project.catalog.model.view.ProductListItemView org.company.project.catalog.dto.ProductListItemDto org.company.project.common.dto.ProductListItemDto - Computist
2
如果我是你,我会在服务层(存储计算值的地方)使用一个包含我所需属性的POJO + 从数据库检索到的属性,我将在model.jdbc包中以数据库表的名称精确调用它。我将使用第一个POJO值将DTO发送到视图,只是为了将所需的值移动到表示层,在此DTO中定义json注释或视图注释,我将把这个DTO放在应用程序模块包中的dto文件夹中。 - Koitoer

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