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

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

我的 POJO。

class Coordinates {

    private final BigDecimal latitude
    private final BigDecimal longitude

    ...
}

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

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

【问题讨论】:

标签: java spring jpa spring-boot spring-data


【解决方案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)),你能把这个东西放在其他地方吗:否,编译器不喜欢,请输入实体请stackoverflow.com/questions/49056084/…
【解决方案2】:

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

@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();
        ......
    }
    

    【讨论】:

    • 没看到 ;(
    猜你喜欢
    • 2018-09-15
    • 2016-07-19
    • 1970-01-01
    • 2020-04-12
    • 2019-02-17
    • 1970-01-01
    • 1970-01-01
    • 2019-03-01
    相关资源
    最近更新 更多