java 我应该将实体转换为 Repository 对象内的 DTO 并将其返回到服务层吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31743017/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 19:03:43  来源:igfitidea点击:

Should I convert an entity to a DTO inside a Repository object and return it to the service layer?

javaweb-servicesgwtabstraction-layer

提问by displayname

I am trying to get an answer to the two quite similar questions here:

我试图在这里得到两个非常相似的问题的答案:

Should I convert an entity to a DTO inside a Repository object and return it to the Service Layer?

我应该将实体转换为 Repository 对象内的 DTO 并将其返回到服务层吗?

or

或者

Is it okay to return DTO objects from the Repository Layer?

从存储库层返回 DTO 对象是否可以?

Right now I am stuck in my Servlet (Servie Layer) that e.g. tries to retrieve all Restaurantobjects from a RestaurantOwnerRepository:

现在我被困在我的 Servlet(服务层)中,例如尝试从以下位置检索所有Restaurant对象RestaurantOwnerRepository

// RestaurantOwnerService (Servlet)

@Override
@Transactional
public List<RestaurantDTO> getAvailableRestaurants() {

    List<Restaurant> availableRestaurants = restaurantOwnerRepository.getRestaurants(getSessionId());

    return null;
}

where Restaurantis a @Entityannotated class - which appears to be the first thing I shouldn't do because the Service Layer does now know about a very low-level object which imho violates the attempt to abstract my data in each layer.

whereRestaurant是一个带@Entity注释的类 - 这似乎是我不应该做的第一件事,因为服务层现在确实知道一个非常低级的对象,恕我直言,它违反了在每一层中抽象我的数据的尝试。

That wouldn't be the case if I e.g. converted each Restaurantto a RestaurantDTO- but should I do that?

如果我将每个都转换Restaurant为 a RestaurantDTO- 但我应该这样做吗?

Basically change:

基本改变:

// RestaurantOwnerRepository

@Override
public List<Restaurant> getRestaurants(String sessionId) {

    RestaurantOwner restaurantOwner = this.get(sessionId);

    // .. getting restaurants ..

    return availableRestaurants;
}

to

// RestaurantOwnerRepository

@Override
public List<Restaurant> getRestaurants(String sessionId) {

    RestaurantOwner restaurantOwner = this.get(sessionId);

    // .. getting restaurants ..

    return ConvertEntity.convertRestaurants(availableRestaurants);
}

and have a util ConvertEntityfor everyentity like this for example:

ConvertEntity每个实体提供一个实用程序,例如:

public class ConvertEntity {

    public static List<RestaurantDTO> convertRestaurants(List<Restaurant> restaurants) {
        // ...
    }

}

but this just does not feel like the best solution to me.. what could I do here?

但这对我来说并不是最好的解决方案..我能在这里做什么?



One important thing to mentionwould be that this comes form a GWT project. That means that I am using e.g. RestaurantDTOon the server and on the client side as it is contained inside a sharedproject.

需要提及的一件重要事情是,这来自一个 GWT 项目。这意味着我RestaurantDTO在服务器和客户端上使用 eg ,因为它包含在共享项目中。

回答by fatih

It's more clear now after your comment. Let's try again:

在您发表评论后,现在更清楚了。让我们再试一次:

First, some clarifications:Your RestaurantOwnerRepositoryimplements the repository pattern. Your @Entityannotated objects are hibernate entities and also DAO proxies. Your RestaurantOwnerServiceis a GWT-Service which can only return a DTO shared with the client and server.

首先,澄清一下:RestaurantOwnerRepository实现了存储库模式。您的@Entity注释对象是休眠实体,也是 DAO 代理。您RestaurantOwnerService是一个 GWT 服务,它只能返回与客户端和服务器共享的 DTO。

So in a very simple server-side setup, you have a DB-Backend, access to the data via hibernate as a persistence layer, and a service layer as rest-service. In such a setup your hibernate entities are shared among the whole server side code. Your service layer is converting the entities to json format, for example. Deal?

所以在一个非常简单的服务器端设置中,你有一个 DB-Backend,通过 hibernate 访问数据作为持久层,服务层作为休息服务。在这样的设置中,您的休眠实体在整个服务器端代码之间共享。例如,您的服务层正在将实体转换为 json 格式。交易?

Your "advanced" setup

您的“高级”设置

  • Persistence layer
    • with Hibernate (delivering @Entity-Annotated objects)
    • maybe other stuff, too
  • Repository Layer (unclear for you what to return)
  • Service Layer (GWT Servlets, delivering DTOs which are shared with the client side)
  • 持久层
    • 使用 Hibernate(提供 @Entity-Annotated 对象)
    • 也许还有其他东西
  • 存储库层(不清楚返回什么)
  • 服务层(GWT Servlets,提供与客户端共享的 DTO)

Definition of Repository-Layer:In my opinion, it's an abstraction for different data/persistence layers. It doesn't provide business logic, which is more the purpose of a further business layer. The business layer compiles the outputs of the upper layer together, makes computations and returns the results. But looking according to your comment, this may also be the case in your repository layer. But it's ok for our clarification.

Repository-Layer 的定义:在我看来,它是对不同数据/持久层的抽象。它不提供业务逻辑,这更多的是进一步业务层的目的。业务层将上层的输出编译在一起,进行计算并返回结果。但是根据您的评论,您的存储库层也可能是这种情况。但我们可以澄清一下。

Your question:Is it okay to return DTO objects from the Repository Layer?

您的问题:是否可以从存储库层返回 DTO 对象?

Answer:No, it is not really okay to return a DTO from the "repository" layer.

回答:不,从“存储库”层返回 DTO 并不是很好。

Why:1. Your DTO is a domain entity transferred into a format which can be sent to the client side. It has limitations so that some server side libraries cannot be used in them. 2. Consider the case that you also want to provide other service layers. A REST-Interface maybe, another GUI-Framework maybe. They all have their own limitations for transferring the domain entities. Do you really want to duplicate the repository layer for each service layer? 3. Consider the case where you want to extend your repository/business layer so that it will use the output of your RestaurantOwnerRepository. Do you really want to work on DTOs there?

为什么:1. 你的 DTO 是一个域实体,转换成可以发送到客户端的格式。它有一些限制,因此无法在其中使用某些服务器端库。2. 考虑您还想提供其他服务层的情况。一个 REST 接口可能,另一个 GUI 框架可能。它们在传输域实体方面都有自己的限制。您真的要为每个服务层复制存储库层吗?3. 考虑您想要扩展存储库/业务层的情况,以便它使用您的RestaurantOwnerRepository. 你真的想在那里从事 DTO 工作吗?

These are why the creation of a DTO is the purpose of a service layer. So the DTO is shared among the client side, and your service layer. In the same sense, you need objects, shared among the service layer and your repository layer. I call these domain entities. These are returned from the repository layer and used by the service layer. Again the same between the repository layer and persistence layer. The persistence layer for example returns the Hibernate entities which are used on the repository layer.

这就是为什么创建 DTO 是服务层的目的。因此 DTO 在客户端和您的服务层之间共享。同样,您需要在服务层和存储库层之间共享的对象。我称这些域实体。这些从存储库层返回并由服务层使用。存储库层和持久层之间也一样。例如,持久层返回在存储库层上使用的 Hibernate 实体。

In most cases, it is ok to propagate your objects from multiple layers downwards. So you can return your hibernate entites from the repository layer to the service layer. Newer versions of GWT even allow to use JPA-entities on the client side with a special setup. So your service layer can further return your persistence entities.

在大多数情况下,可以从多个层向下传播您的对象。因此,您可以将您的休眠实体从存储库层返回到服务层。较新版本的 GWT 甚至允许通过特殊设置在客户端使用 JPA 实体。所以你的服务层可以进一步返回你的持久化实体。