我有一个实体,在将其返回给用户之前需要稍作修改。据我了解,最好的方法是使用数据传输对象。
这很好,但是后来我添加了一个子实体。我再次为子实体创建了一个DTO。这是存储库的代码:
@Repository
public interface DrawingReleaseRepository extends CrudRepository<DrawingRelease, Integer> {
@Query("SELECT new com.engineering.dto.drawings.DrawingReleaseDTO("
+ "dwgrel.drawingReleaseID,"
+ "relType"
+ ") FROM DrawingRelease dwgrel "
+ "JOIN dwgrel.releaseType relType "
+ "WHERE dwgrel.drawingReleaseID = ?1")
DrawingReleaseDTO getDrawingRelease(int drawingReleaseID);
}
DrawingReleaseDTO的构造函数是这样的:
public DrawingReleaseDTO(int drawingReleaseID, DrawingReleaseType releaseType) {
this.drawingReleaseID = drawingReleaseID;
this.releaseType = new DrawingReleaseTypeDTO(releaseType);
}
在服务层中,我现在可以操纵数据并将其返回给客户端,但是更改不会持久保存到数据库中(这是我想要的):
@Override
public DrawingReleaseDTO findByID(int id) {
DrawingReleaseDTO dto = repository.getDrawingRelease(id);
dto.getReleaseType().setCustom1(true);
return dto;
}
该方案的问题是效率不是很高。我的意思是Hibernate执行两个查询-一个查询DrawingRelease
和一个查询DrawingReleaseType
。
我认为解决此问题的方法将是指定JOIN FETCH dwgrel.releaseType relType
,因为这将强制休眠一次获取所有数据,但这会产生错误:
查询指定联接获取,但已获取的所有者 选择列表中不存在关联
是否有使用DTO的方法,包括子实体的数据,并全部使用有效的查询?
答案 0 :(得分:1)
问题是您将DTO和实体混合在一起。
DTO不应引用实体,第二个查询来自初始化子实体。
此外,将实体传递给DTO也是一种反模式:
this.releaseType = new DrawingReleaseTypeDTO(releaseType);
您需要从列投影构造DTO。有关更多详细信息,请查看this article。
答案 1 :(得分:0)
这是Blaze-Persistence Entity Views的完美用例,它将通过生成仅获取相关属性的JPQL / HQL查询来完全满足您的要求,并提高性能。 尽管我不了解您的模型,但据我了解,在您的模型中使用实体视图可能像这样
interface DrawingReleaseRepository extends JpaRepository<DrawingReleaseDTO, Long> {
}
DrawingReleaseDTO dto = drawingReleaseRepository.findById(id);
setup正确时,您可以将该实体视图与spring-data存储库一起使用
SELECT drawingRelease.id, drawingReleaseType.custom1
FROM DrawingRelease drawingRelease
LEFT JOIN drawingRelease.drawingReleaseType drawingReleaseType
WHERE drawingRelease.id = :id
它将生成这样的JPQL / HQL查询
type COMPANY {
"AIRLINE SEGMENT": String
AIRLINE_TYPE: String
}