使用本机查询从 Spring Data 返回自定义对象

Posted

技术标签:

【中文标题】使用本机查询从 Spring Data 返回自定义对象【英文标题】:Return custom object from Spring Data with Native Query 【发布时间】:2017-08-11 03:45:45 【问题描述】:

我的问题基于another post。如何使用本机查询实现相同的目标?本机查询不允许 JPQL,因此也不允许新实例。

我的 POJO。

class Coordinates 

    private final BigDecimal latitude
    private final BigDecimal longitude

    ...

我的数据库表包含城市周长的坐标,所以有三列:city_name、纬度、经度。每个城市都包含很多(真的,很多)周界坐标,这些坐标将用于在 Google 地图中构建阴影区域。

我打算在该表上构建一个简单的本机查询,该查询应返回坐标列表。

【问题讨论】:

这是一个很好的example。 请参考我在***.com/questions/29082749/…的回答 这能回答你的问题吗? Spring Data JPA map the native query result to Non-Entity POJO @Lu55 这个问题自 2017 年以来已经有了答案。 【参考方案1】:

在another post 上找到了答案。基本上我使用了SqlResultSetMappingConstructorResult(没有其他办法),特别注意对上述帖子的已接受答案的评论:您需要将@NamedNativeQuery 注释添加到所用@ 的实体中987654326@ AND 在实体名称前加上 . 否则将不起作用。

示例:

@Entity
@Table(name = "grupo_setorial")
@SqlResultSetMapping(
        name = "mapeamentoDeQuadrantes",
        classes = 
                @ConstructorResult(
                        targetClass = Coordenada.class,
                        columns = 
                                @ColumnResult(name = "latitude"),
                                @ColumnResult(name = "longitude")
                        
                )
        
)
@NamedNativeQuery(
        name = "GrupoCensitario.obterPerimetroDosSetores",
        query = "SELECT latitude as latitude, longitude as longitude FROM coordenadas where id_setor IN (:setores)",
        resultSetMapping = "mapeamentoDeQuadrantes"
)
public class GrupoCensitario 

【讨论】:

@Manu 我这样做已经有一段时间了,所以老实说我不记得“在实体名称前加上.”部分,但我粘贴在当前生产的上方。跨度> 说明了 Prepend 实体名称部分,因为它很重要。如果您的 nativequery 名称是 obterPerimetroDosSetores 并且实体名称是 GrupoCensitario,那么您需要在 @NamedNativeQuery for Spring 中将其命名为 GrupoCensitario.obterPerimetroDosSetores 以便能够从 repo 中找出 obterPerimetroDosSetores 查询在 GrupoCensitario 类中。希望对您有所帮助。 对于 1 追随我:你将很快面临这个问题(需要在 repo 中为函数添加 @Query(nativeQuery=true)),你能把这个东西放在其他地方吗:否,编译器不喜欢,请输入实体请***.com/questions/49056084/…【参考方案2】:

这是https://jira.spring.io/browse/DATAJPA-980,Here 是一个演示该问题的项目。

@Query(value = "SELECT name AS name, age AS age FROM Person", nativeQuery = true)
List<PersonSummary> findAllProjectedNativeQuery();

它在 Hibernate 5.2.11 附带的 Spring Data JPA 2.0 GA (Kay) 版本中得到修复。

Spring Data 1.10.12 (Ingalls) 和 1.11.8 (Hopper) 的问题也已解决,但需要在 Hibernate 5.2.11 上运行才能工作。

【讨论】:

有趣的东西。在接受答案之前,我会尝试一下。但我想知道:如果我没有实体怎么办?我将无法使用org.springframework.data.repository.*。在这种情况下,我会说 johncena 的答案就是那个。 @SidneydeMoraes PersonSummary 不是实体 @SidneydeMoraes 如果您根本没有实体,为什么还要使用 spring-data 存储库?此查找器只能作为已创建的 Spring 数据存储库的补充方法。否则我会选择普通的 jdbcTemplate+rowmapper 解决方案。 我想保持使用带有单个注释(例如 @Query)的接口存储库的便利性,而不必处理注入实体管理器和所有这些东西。 您链接到的票证对于版本 1.10.12 和 1.11.8 也是固定的,但给定的代码仍然不起作用.. :-( 根据作者的说法,您需要 Hibernate Hibernate 5.2。 11 或更高版本..【参考方案3】:

您必须使用 sql result set mapping,它是 JPA 的一部分。

【讨论】:

我发现 SqlResultSetMapping 本身只适用于实体,不适用于非实体 POJO 的 as seen on this post。我会试试ConstructorResult 所以,ConstructorResult 是要走的路。请检查我添加的答案。【参考方案4】:

如果您使用的是最新版本的spring-data 并且还使用Repositories,我个人认为Itsallas 的答案会导致正确的解决方案。

实际上,我现在还没有了解(Spring Data)Projections,需要一点时间来了解他在示例中展示的内容。

因此我只想添加Spring Data JPA - Reference Documentation的链接,看看Projections chapter。

Spring Data 查询方法通常返回由存储库管理的聚合根的一个或多个实例。但是,有时可能需要基于这些类型的某些属性创建投影。 Spring Data 允许对专用返回类型进行建模,以更有选择性地检索托管聚合的部分视图。

【讨论】:

【参考方案5】:

我找到的答案:

public interface UserEventRepository extends JpaRepository<UserEvent, Long> 

    List<UserEvent> findAllByUserId(Long userId);

    @Query(value = "SELECT user_id FROM user_event ue " +
                   "WHERE ue.user_id = :userId", nativeQuery = true)
    List<Long> findUserIdByEventId(@Param("userId") Long userId);

这样我们会返回 List of Long - id 列表。这里的关键是我们将 nativeQuery 属性设置为 true。值本身就是我们要执行的查询。

我希望这会有所帮助。这似乎是一个明确的解决方案。

【讨论】:

感谢您的贡献,但这个问题已经有一个公认的答案。此外,问题涉及返回自定义值对象而不是实体,这是 spring-data 存储库的常规使用。 @reneta 本地查询速度快吗? @KumaresanPerumal - 我不确定,我认为没有速度差异 - 当您有更复杂的查询或不寻常的查询时,通常使用本机查询。【参考方案6】:

投影解决方案是最好的。 (id查询只是一个例子,你可以使用extends CRUD操作)

只需添加接口作为对查询的响应

@Query(select * from tableA where tableA = :id)
MyInterface findTableAbyId(@Param(value = "id") Long id)

public interface MyInterface () 
    String getName();
    String getLastName();
    ......

【讨论】:

没看到 ;(

以上是关于使用本机查询从 Spring Data 返回自定义对象的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA 查询结果返回至自定义实体

从Spring Data Jpa查询返回的对象具有空值

如何在本机查询中使用 NVL 或 COALESCE 获取 Spring Data JPA 中的值列表

用于在 Spring Data Jpa 中从多个表中获取数据的自定义查询

最新的 Spring Data/Hibernate 在本机查询中不支持 java.time.LocalDate?

Spring Data JPA - 带有“@Param Date”的自定义@Query 不起作用