繁体   English   中英

Spring Data JPA:查询如何返回非实体对象或对象列表?

[英]Spring Data JPA: How can Query return Non- Entities Objects or List of Objects?

我在我的项目中使用 spring 数据 JPA。 我正在玩数百万条记录。 我有一个要求,我必须为各种表获取数据并构建一个对象,然后在 UI 上绘制它。 现在如何实现我的 Spring 数据存储库。 我读过它可以通过命名本机查询来实现。

如果命名原生查询没有返回实体或实体列表,我们可以使用@SqlResultSetMapping 注解将查询结果映射到正确的返回类型。

但是当我尝试使用@SqlResultSetMapping它正在使用另一个entityResult 意思是我理解的是它只是将一些查询结果转换为实体结果集,但我想要一个非实体对象的结果集。

@SqlResultSetMapping(
    name="studentPercentile",
    entities={
        @EntityResult(
           entityClass=CustomStudent.class,
              fields={
                  @FieldResult(name="id", column="ID"),
                  @FieldResult(name="firstName", column="FIRST_NAME"),
                   @FieldResult(name="lastName", column="LAST_NAME")
              }         
        )
   }
) 
@NamedNativeQuery(
    name="findStudentPercentile", 
    query="SELECT * FROM STUDENT", 
    resultSetMapping="studentPercentile")

在上面的示例中,我只是想将结果从学生实体获取到另一个不是实体的 pojo ' CustomStudent '。 这个例子我只是为了 POC 目的而尝试执行,实际用例非常复杂,复杂的查询返回不同的结果集)。

如何实现上述用例? 除了使用我的存储库方法返回非实体对象的名称查询之外,还有其他方法吗?

你可以做类似的事情

@NamedQuery(name="findWhatever", query="SELECT new path.to.dto.MyDto(e.id, e.otherProperty) FROM Student e WHERE e.id = ?1")

然后 MyDto 对象只需要一个用正确字段定义的构造函数,即

public MyDto(String id, String otherProperty) { this.id = id; this.otherProperty = otherProperty; }

当我第一次遇到这个问题时,我感到非常惊讶,但是,是的,您只能使用 @SqlResultSetMapping 将查询结果映射到标量和托管实体。

我猜你能做的最好的事情就是跳过自动映射。 没有映射的查询将返回List<Object[]>并且您可以按照您需要的方式映射它。

另一种方法是使用@MappedSuperclass。 表示为@MappedSuperclass(在您的情况下为CustomStudent)的类可以(虽然不确定100%)在@SqlResultSetMapping 中使用。 但是您需要引入继承层次结构,即您的 Student 实体必须扩展 CustomStudent。 从正确的 OO 设计中大部分时间会很糟糕,因为继承会有点人为......

JPA 2.1 ConstructorResult怎么样?

@SqlResultSetMapping(
    name="studentPercentile",
    classes={
        @ConstructorResult(
            targetClass=CustomStudent.class,
            columns={
                @ColumnResult(name="ID"),
                @ColumnResult(name="FIRST_NAME"),
                @ColumnResult(name="LAST_NAME")
            }
        )
    }
)

@NamedNativeQuery(name="findStudentPercentile", query="SELECT * FROM STUDENT", resultSetMapping="studentPercentile")

我们还可以使用 JSON 帮助进行解析。

类级别声明。

@Autowired
private EntityManager em;
private ObjectMapper mapper = new ObjectMapper(); 

主要代码。

Query query = em.createNativeQuery(argQueryString);
NativeQueryImpl nativeQuery = (NativeQueryImpl) query;
nativeQuery.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
List<Map<String,Object>> result = nativeQuery.getResultList();
List<CustomStudent> resultList = result.stream()
   .map(o -> {
         try {
              return 
            mapper.readValue(mapper.writeValueAsString(o),CustomStudent.class);
       } catch (Exception e) {
           ApplicationLogger.logger.error(e.getMessage(),e);
       }
     return null;
    }).collect(Collectors.toList());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM