Spring Data - 投影和@Query嵌套属性

4

Assume I have those DTO:

public interface ForumDTO extends ForumBaseDTO{
    Integer getId();
    ThreadDTO getLastThread();
}
public interface ThreadDTO {
    Integer getId();
    Integer getCommentCount()
}

在我的代码库中,我使用这些数据传输对象作为投影来执行以下查询:
   @Query("select forum.id as id, " +
   "forum.name as name, " +
   "lastThread.id as lastThread_id " +
   "from Forum forum " +
   "inner join forum.lastThread as lastThread " +
   "where forum.parent.id = ?:"
   )
   Iterable<ForumDTO> findAllByParentId(Integer id);

使用这个仓库,我可以很好地访问ForumDTO中的id和name,但是对于lastThread,它只返回null。我尝试过as lastThread.Idas lastThread_idas lastThreadId,但都没有起作用。

1个回答

2
你已经接近成功了。
你需要从论坛访问它,以跟踪外键:
@Query("select forum.id as id, " +
   "forum.name as name, " +
   "**forum.lastThread.id** as lastThread_id " +
   "from Forum forum " +
   "inner join forum.lastThread as lastThread " +
   "where forum.parent.id = ?:"
   )
   Iterable<ForumDTO> findAllByParentId(Integer id);

话虽如此,但你多做了很多无用功。同样的查询可以写成:

@Query("select forum from Forum where forum.parent.id = :forumId")
Iterable<ForumDTO> findAllByParentId(@Param("forumId")Integer id);

您只需要确保实体上存在指向Parent的外键。

还要注意@Param注释。它使您的参数更容易跟踪,并对数据库进行一些基本类型检查。它非常有用,可以防止SQL注入攻击和UncheckedTypeException


1
但是当ThreadDTO有一个像getCommentCount这样的字段,它是通过使用count(comments.id)计算出来的,你的方法就不起作用了。最初,我使用字段名称,以便可以使用count()函数。 - user2477
这是一个不同的问题。在JPA中,合计有点棘手,但你遇到的问题是因为你没有正确地按照外键路径进行操作。 - Stephan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接