一尘不染

Spring Data JPA将本机查询结果映射到非实体POJO

spring

我有一个带有本地查询的Spring Data Repository方法

@Query(value = "SELECT g.*, gm.* FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId", nativeQuery = true)
    GroupDetails getGroupDetails(@Param("userId") Integer userId, @Param("groupId") Integer groupId);

并且我想将结果映射到Non-Entity POJO GroupDetails

是否可以,如果可以,请提供示例吗?


阅读 972

收藏
2020-04-11

共2个答案

一尘不染

假设在Orid的答案中使用GroupDetails,你是否尝试过JPA 2.1 @ConstructorResult?

@SqlResultSetMapping(
    name="groupDetailsMapping",
    classes={
        @ConstructorResult(
            targetClass=GroupDetails.class,
            columns={
                @ColumnResult(name="GROUP_ID"),
                @ColumnResult(name="USER_ID")
            }
        )
    }
)

@NamedNativeQuery(name="getGroupDetails", query="SELECT g.*, gm.* FROM group g LEFT JOIN group_members gm ON g.group_id = gm.group_id and gm.user_id = :userId WHERE g.group_id = :groupId", resultSetMapping="groupDetailsMapping")

并在存储库界面中使用以下命令:

GroupDetails getGroupDetails(@Param("userId") Integer userId, @Param("groupId") Integer groupId);

根据springJPA的数据文件,spring将首先尝试找到一个名为查询匹配你的方法名-因此使用@NamedNativeQuery@SqlResultSetMapping并且@ConstructorResult你应该能够实现这一行为

2020-04-11
一尘不染

我认为最简单的方法是使用所谓的投影。它可以将查询结果映射到接口。使用SqlResultSetMapping不方便,并使你的代码难看:)。

正确的示例来自spring data JPA源代码:

public interface UserRepository extends JpaRepository<User, Integer> {

   @Query(value = "SELECT firstname, lastname FROM SD_User WHERE id = ?1", nativeQuery = true)
   NameOnly findByNativeQuery(Integer id);

   public static interface NameOnly {

     String getFirstname();

     String getLastname();

  }
}

你也可以使用此方法获取投影列表。

请查看此spring数据JPA文档条目,以获取有关预测的更多信息。

注1:

请记住,将你的User实体定义为普通对象-投影界面中的字段必须与该实体中的字段匹配。否则,字段映射可能会损坏(getFirstname()可能返回姓氏等的值)。

笔记2:

如果使用SELECT table.column ...符号,请始终定义与实体名称匹配的别名。例如,此代码将无法正常工作(投影将为每个getter返回null):

@Query(value = "SELECT user.firstname, user.lastname FROM SD_User user WHERE id = ?1", nativeQuery = true)
NameOnly findByNativeQuery(Integer id);

但这很好用:

@Query(value = "SELECT user.firstname AS firstname, user.lastname AS lastname FROM SD_User user WHERE id = ?1", nativeQuery = true)
NameOnly findByNativeQuery(Integer id);

对于更复杂的查询,我宁愿使用JdbcTemplate自定义存储库。

2020-04-11