【问题标题】:What is the relationship between DTO and lazy-loading in HibernateHibernate中DTO和延迟加载有什么关系
【发布时间】:2018-11-22 10:56:51
【问题描述】:

我知道什么是 DTO:一个在进程之间携带数据以减少方法调用次数的对象。 我知道什么是休眠中的延迟加载。

我在“使用 JHipster 进行全栈开发”一书中读到这句话: JHipster 在服务器端使用 DTO(数据传输对象)和 VM(视图模型)。 DTO 用于将数据从服务层传输到资源层和从资源层传输。它们会中断 Hibernate 事务并避免资源层触发进一步的延迟加载。

我不明白DTO和延迟加载的关系。

【问题讨论】:

    标签: java hibernate lazy-loading jhipster dto


    【解决方案1】:

    延迟加载适用于实体,而不是 DTO。

    JPA 实体可以表示为 POJO 或 Proxy。

    使用EntityManager.find 会给你一个 POJO:

    Post post = entityManager.find(Post.class, postId);
    

    虽然EtityManager.getReference 方法为您提供了一个代理:

    Post post = entityManager.getReference(Post.class, postId);
    

    POJO 的基本属性已初始化,因为执行了 SELECT 语句来获取实体。代理在创建时不会命中数据库。仅根据提供的实体标识符设置 id。只有您访问 Proxy 属性,才会执行 SELECT 语句。

    代理也用于默认使用FetchType.LAZY 策略的集合(例如@OneToMany 或@ManyToMany)。访问 LAZY 集合后,将执行 SELECT 语句来获取关联的集合。

    现在,DTO 基于投影,因此在填充 DTO 之前执行 SELECT 语句。为此,您可以说每次都急切地加载 DTO。

    对于只读投影,DTO 比实体更有效,因为您只加载明确请求的表列。

    【讨论】:

    • 我应该使用 DTO 还是只读实体进行只读操作?
    • 这取决于您需要获取多少数据。如果您需要整个实体,请使用它。如果您只需要该实体的一个子集,请使用 DTO。
    • 谢谢弗拉德。在表示层访问实体是否合法?
    • 由于UI通常对来自服务器的JSON数据进行操作,所以将实体转换为JSON就可以了。因此,如果实体没有代理,则与将 DTO 序列化为 JSON 没有太大区别。如果代理未初始化并且映射器尝试访问它们,则代理通常会使此过程复杂化。
    【解决方案2】:

    如果您在启用 LazyLoading 的情况下将 Hibernate 托管的持久实体传递给资源层,则资源层将调用 get-methods 以读取它们的属性,其中一些可能当时尚未初始化。然后,Hibernate 将从持久化存储中延迟加载该特定属性的数据,发送一条 SQL 语句(可能每次启动并提交一个新事务)并等待非常慢的响应。如果这种情况发生数百次,每次都必须初始化另一个属性,每次触发延迟加载,用户都必须等待......

    如果您在服务层中准备了一个 DTO,其中包含与资源层相关的所有数据,则对该 DTO 的读取访问效率很高,而不会因任何get-方法调用而命中数据库,因为所有相关内容都是已经在记忆中了。不会触发后续的延迟加载。

    【讨论】:

      【解决方案3】:

      简单来说:如果您调用延迟加载标记字段的 getter,Hibernate 将对该数据进行 db 查询。

      这是您不应将实体作为后端响应返回的原因之一...任何 JSON 转换(序列化)/getter 调用都会触发不必要的数据加载。

      而 DTO 专门用于根据用途传输数据,您从这些实体创建 DTO(可以从一个实体创建多个 DTO)并仅选择所需的数据字段

      例如 用户实体:拥有用户详细信息和好友列表 UserDetailsDTO:只需要详细信息,不需要映射到用户的 1000 个朋友......以及他们的朋友...... UserFriendsDTO:我们可以选择性地获取此 DTO 的好友名称或 ID

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-12
        • 1970-01-01
        • 1970-01-01
        • 2011-07-25
        • 1970-01-01
        • 2015-05-24
        • 1970-01-01
        相关资源
        最近更新 更多