Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Hibernate 使用spring数据jpa的最高效数据传输对象_Hibernate_Jpa_Spring Data Jpa - Fatal编程技术网

Hibernate 使用spring数据jpa的最高效数据传输对象

Hibernate 使用spring数据jpa的最高效数据传输对象,hibernate,jpa,spring-data-jpa,Hibernate,Jpa,Spring Data Jpa,我有一个实体,在返回给用户之前需要稍微修改一下。据我所知,最好的方法是使用数据传输对象 这很好,但是我添加了一个子实体。我再次为子实体创建了DTO。以下是存储库的代码: @Repository public interface DrawingReleaseRepository extends CrudRepository<DrawingRelease, Integer> { @Query("SELECT new com.engineering.dto.drawings.Dra

我有一个实体,在返回给用户之前需要稍微修改一下。据我所知,最好的方法是使用数据传输对象

这很好,但是我添加了一个子实体。我再次为子实体创建了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);
}
在我的服务层中,我现在可以操作数据并将其返回到客户端,但更改不会持久化到数据库(这是我想要的):

这种情况的问题是效率不高。我的意思是Hibernate执行两个查询—一个用于
DrawingRelease
,另一个用于
DrawingReleaseType

我认为解决这个问题的方法是指定
JOIN FETCH dwgrel.releaseType relType
,因为这会迫使hibernate一次获取所有数据,但会产生错误:

查询指定的联接获取,但获取的联接的所有者 选择列表中不存在关联


有没有一种方法可以使用DTO,包括子实体的数据,并让它们都使用高效的查询?

问题是您将DTO和实体混合在一起了

DTO不应该引用实体,第二个查询来自初始化子实体

此外,将实体传递给DTO是一种:


您需要从列投影中构造DTO。

这是一个完美的用例,它将完全满足您的需要,并通过生成只获取相关属性的JPQL/HQL查询来提高性能。 虽然我不知道您的模型,但据我所知,对您的模型使用实体视图可能是这样的

@EntityView(DrawingRelease.class)
public interface DrawingReleaseDTO
  int getDrawingReleaseID();
  DrawingReleaseTypeDTO getReleaseType();

  @EntityView(DrawingReleaseType.class)
  interface DrawingReleaseTypeDTO {
    boolean isCustom1();
  }
}
如果正确,您可以将该实体视图与spring数据存储库一起使用

interface DrawingReleaseRepository extends JpaRepository<DrawingReleaseDTO, Long> {
}

DrawingReleaseDTO dto = drawingReleaseRepository.findById(id);

太长,读不下去了第一句话TDO是一个参数,例如用作REST输出或输入参数,而不是“修改”或转换任何内容。您从一开始就错了。@Antoniossss参考更多关于我为什么使用DTO的背景信息。你还有什么建议吗?我只是提醒你,DTO不能像你说的那样“转换”任何东西。我有点不理解DTO和某些东西没有持久化到数据库中这一问题之间的联系。也许这只是我的疲劳。对DrawingRelease的质疑来自哪里?指定的查询只有dwgrel.drawingReleaseID,因此没有生成DrawingRelease实例。您的DrawingReleaseType是否可以引用DrawingRelease?如果是这样,请将其标记为lazy以避免获取。@Chris我认为该查询正在构建DrawingRelease实例。它使用该实例中的drawingReleaseID来构建DrawingReleaseDTO。我不想避免抓取——我希望它在一个查询中发生。也许我也应该包含这段代码,但是如果DTO构造函数具有
DTOproperty1=releaseType.getPropertyX()
等等,那么将实体传递给DTO仍然是错误的吗?我知道第二个查询来自初始化子实体,但是有没有一种方法可以在一个查询中同时初始化它们?实际上,我将有许多子实体,如果我能在一个查询中获得我所需要的所有数据,那似乎会更有效。还是检索实体然后构造DTO的正确方法?但是,您不会失去不检索托管实体的好处吗?是的,这是错误的。如果需要实体,请使用实体查询。如果需要DTO,请使用DTO投影。但是不要把它们混在一起。你有没有关于如何使用子DTO进行DTO的例子?你的文章只使用了原生类型。是的,这是一个很好的例子,说明了同一个对象的层次结构,但是如果有一个不同对象的子对象,比如我的问题中的子对象呢?是否有一种方法可以在一个查询中检索所有数据(如JOIN-FETCH),还是只需执行一个JOIN并让Hibernate运行多个查询即可获取所有子数据?
this.releaseType = new DrawingReleaseTypeDTO(releaseType);
@EntityView(DrawingRelease.class)
public interface DrawingReleaseDTO
  int getDrawingReleaseID();
  DrawingReleaseTypeDTO getReleaseType();

  @EntityView(DrawingReleaseType.class)
  interface DrawingReleaseTypeDTO {
    boolean isCustom1();
  }
}
interface DrawingReleaseRepository extends JpaRepository<DrawingReleaseDTO, Long> {
}

DrawingReleaseDTO dto = drawingReleaseRepository.findById(id);
SELECT drawingRelease.id, drawingReleaseType.custom1 
FROM DrawingRelease drawingRelease 
LEFT JOIN drawingRelease.drawingReleaseType drawingReleaseType 
WHERE drawingRelease.id = :id