Java Spring Data JPA:查询如何返回非实体对象或对象列表?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16420697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Data JPA: How can Query return Non- Entities Objects or List of Objects?
提问by DHRUV BANSAL
I am using spring data JPA in my project. I am playing with millions of records. I have a requirement where I have to fetch data for various tables and build a object and then paint it on a UI. Now how to achieve this my Spring data Repositories. I have read that it can be achieved by Named native queries.
我在我的项目中使用 spring 数据 JPA。我正在玩数百万条记录。我有一个要求,我必须为各种表获取数据并构建一个对象,然后在 UI 上绘制它。现在如何实现我的 Spring 数据存储库。我读过它可以通过命名本机查询来实现。
If the named native query does not return an entity or a list of entities, we can map the query result to a correct return type by using the @SqlResultSetMapping annotation.
如果命名原生查询没有返回实体或实体列表,我们可以使用@SqlResultSetMapping 注解将查询结果映射到正确的返回类型。
But when I am trying to use @SqlResultSetMapping
it is taking another entityResult. Mean what I understand is that it is just transformation some query result to entity result set only, but I want a result set of non - entities objects.
但是当我尝试使用@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")
In above example I am just trying to get a results from student Entity into another pojo 'CustomStudent' which is not a entity. (This example I am trying to execute just for POC purpose, actual usecase is much complicated, with complicated query returning different resultset).
在上面的示例中,我只是想将结果从学生实体获取到另一个不是实体的pojo ' CustomStudent'。(这个例子我只是为了 POC 目的而尝试执行,实际用例非常复杂,复杂的查询返回不同的结果集)。
How to achieve above usecase? Is there any other way besides using name query that my repository method returning Non - Entities objects?
如何实现上述用例?除了使用我的存储库方法返回非实体对象的名称查询之外,还有其他方法吗?
采纳答案by Piotr Kochański
I was deeply surprised when I came accross this for the first time but, yes, you can map query results using @SqlResultSetMapping only to scalars and managed entities.
当我第一次遇到这个问题时,我感到非常惊讶,但是,是的,您只能使用 @SqlResultSetMapping 将查询结果映射到标量和托管实体。
The best you can do, I guess, is to skip automatic mapping. Query without mapping would return List<Object[]>
and you can map it the way you need.
我猜你能做的最好的事情就是跳过自动映射。没有映射的查询将返回List<Object[]>
,您可以按需要的方式映射它。
Another approach would be to use @MappedSuperclass. The class denoted as @MappedSuperclass (CustomStudent in your case) can be (not sure 100%, though) used in @SqlResultSetMapping. but you need to introduce inheritance hierarchy, that is your Student entity must extend CustomStudent. That would suck most of the time from the proper OO design, because inheritance would be a little bit artificial...
另一种方法是使用@MappedSuperclass。表示为@MappedSuperclass(在您的情况下为CustomStudent)的类可以(虽然不确定100%)在@SqlResultSetMapping 中使用。但是您需要引入继承层次结构,即您的 Student 实体必须扩展 CustomStudent。从正确的 OO 设计中大部分时间会很糟糕,因为继承会有点人为......
回答by tlavarea
You can do something like
你可以做类似的事情
@NamedQuery(name="findWhatever", query="SELECT new path.to.dto.MyDto(e.id, e.otherProperty) FROM Student e WHERE e.id = ?1")
Then the MyDto object would just need a constructor defined with the correct fields i.e.
然后 MyDto 对象只需要一个用正确字段定义的构造函数,即
public MyDto(String id, String otherProperty) { this.id = id; this.otherProperty = otherProperty; }
回答by Daimon
How about JPA 2.1 ConstructorResult?
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")
回答by Kapil Thakkar
We can also parse using JSON help.
我们还可以使用 JSON 帮助进行解析。
Class level declaration.
类级别声明。
@Autowired
private EntityManager em;
private ObjectMapper mapper = new ObjectMapper();
Main Code.
主要代码。
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());