DTO与Hibernate中的延迟加载之间有什么关系

时间:2018-11-22 10:56:51

标签: java hibernate lazy-loading jhipster dto

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

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

我不了解DTO和延迟加载之间的关系。

3 个答案:

答案 0 :(得分:2)

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

如果您在服务层中准备一个DTO,其中包含与资源层相关的所有数据,那么对DTO的读取访问将非常高效,而不会因为任何get方法调用而将数据库打入数据库的风险相关已经在内存中。没有后续的延迟加载。

答案 1 :(得分:2)

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

JPA实体可以表示为POJO或Proxy

正如我在this article中所述,使用EntityManager.find会给您一个POJO:

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

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

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

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

代理还用于默认情况下使用@OneToMany策略的集合(例如@ManyToManyFetchType.LAZY)。访问LAZY集合后,将执行SELECT语句以获取关联的集合。

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

对于只读投影,DTO比实体更有效,因为您仅加载显式请求的表列。有关在JPA和Hibernate中使用DTO的最佳方法的更多详细信息,请查看this article

答案 2 :(得分:1)

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

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

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

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