第28.6 hibernate 手册中提到您不应该使用实体查询进行只读获取,因为它们会请求太多数据。
这是有道理的,我们已经看到复杂的领域模型会导致查询运行时间非常长,尤其是在使用 TableView 时。
手册继续指出:
For read-only transactions, you should fetch DTO projections because they allow you to select just as many columns as you need to fulfill a certain business use case.
但是 AFAIK JPA 没有提供获取这些预测的好方法,您只能使用标准构建器,我们发现它冗长、脆弱并且经常无法正常工作(实现很困难)。
确实,查看 SO 上的各种帖子表明很多人都在使用实体进行读取。 所以我提出的问题如下:
- 正在避免在现实世界的企业应用程序中常见的只读实体查询,我觉得它不是。
- 如果是,人们使用什么工具来使它变得可以忍受,我想到了一个单独的查询 dsl,jOOQ?
- 是否有任何资源为连接到持久层的 Spring 应用程序的架构制定了最佳实践(我正在考虑可能导致问题的其他复杂问题,例如事务管理),似乎每个人似乎采取了一种特别的方法。
最佳答案
你要明白,没有绝对的答案,每个人都会根据自己的经验给你不同的建议/意见。
通常,首选的解决方案是使用 DTO 方法,但如何实现它留给开发人员练习。一些开发人员太懒惰或只是接受/应对使用实体查询可能带来的负面影响。这实际上取决于您的用例和需求。
不过我认为,您正在寻找的是类似 Blaze-Persistence Entity Views 的解决方案.
我创建了该库以允许在 JPA 模型和自定义接口(interface)或抽象类定义的模型之间轻松映射,类似于 Spring Data Projections on steroids。这个想法是您按照自己喜欢的方式定义目标结构(领域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。
使用 Blaze-Persistence 实体 View 的示例用例的 DTO 模型如下所示:
@EntityView(User.class)
public interface UserDto {
@IdMapping
Long getId();
String getName();
Set<RoleDto> getRoles();
@EntityView(Role.class)
interface RoleDto {
@IdMapping
Long getId();
String getName();
}
}
查询是将实体 View 应用于查询,最简单的就是通过 id 进行查询。
UserDto a = entityViewManager.find(entityManager, UserDto.class, id);
Spring Data 集成允许您像使用 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
Page<UserDto> findAll(Pageable pageable);
最好的部分是,它只会获取实际需要的状态!
关于java - 在 JPA/Hibernate 中执行只读操作的最佳实践是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73177513/