38

我在我的项目中使用弹簧数据 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 目的执行此示例,实际用例非常复杂,复杂的查询返回不同的结果集)。

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

4

4 回答 4

26

你可以做类似的事情

@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; }
于 2015-02-24T15:26:54.203 回答
24

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

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

另一种方法是使用@MappedSuperclass。表示为@MappedSuperclass 的类(在您的情况下为CustomStudent)可以(但不确定100%)在@SqlResultSetMapping 中使用。但是您需要引入继承层次结构,即您的学生实体必须扩展 CustomStudent。这会在大多数情况下从正确的 OO 设计中吸走,因为继承会有点人为......

于 2013-05-07T17:01:04.730 回答
18

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")
于 2015-08-12T13:27:38.933 回答
0

我们还可以使用 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());
于 2020-02-10T05:42:12.117 回答