简体   繁体   English

Spring Boot 和 JPA:将数据从多连接查询返回到 GET HTTP 命令时出错

[英]Spring Boot and JPA: error returning data from a multi-join query to a GET HTTP command

I'm on Spring Boot and JPA since few weeks, so maybe the question is relatively trivial to someone.几周以来我一直在使用 Spring Boot 和 JPA,所以这个问题对某人来说可能相对微不足道。 I have an @Entity where I defined a @NamedNativeQuery like:我有一个@Entity,我在其中定义了一个@NamedNativeQuery,例如:

@NamedNativeQuery(
        name = "Device.getMeasuresAndDates",
        query = """
        select a.id, 
        a.device,
        a.deviceManufacturer, 
        b.dateOfMeasure, 
        c.Id, 
        c.componentSerialNumber, 
        c.ComponentMeasure
        from devices a inner join measures b on b.device_id = a.id
        inner join instruments c on c.id = b.instrument_id
        where a.device = :device
        order by b.dateOfMeasure, c.componentSerialNumber
        """,
        resultSetMapping = "MeasuresAndDatesMapping"
        )

the query is defined in the Device entity, as it seems to be the logical place where to put it.查询是在 Device 实体中定义的,因为它似乎是放置它的逻辑位置。 The query returns only proper fields, not all the entities fields that are much more, and most of them are useless to the service.查询只返回适当的字段,而不是所有更多的实体字段,并且其中大多数对服务无用。

then I tried to map the results with @SqlResultSetMapping + @EntityResult;然后我尝试使用 @SqlResultSetMapping + @EntityResult 映射结果; since I do not return all table fields, I do not map all entity properties, I put the entity property names in "name" attribute and the field returned by the query in "column" attribute:因为我不返回所有表字段,所以我不映射所有实体属性,我将实体属性名称放在“name”属性中,将查询返回的字段放在“column”属性中:

@SqlResultSetMapping(
        name = "MeasuresAndDatesMapping",
        entities = {
            @EntityResult(
                    entityClass = Device.class,
                    fields = {
                        @FieldResult(name = "id", column = "a.id"),
                        @FieldResult(name = "device", column = "a.device"),
                        @FieldResult(name = "deviceManufacturer", column = "a.deviceManufacturer")
                    }
            ),
            @EntityResult(
                entityClass = Measure.class,
                fields = {
                    @FieldResult(name = "dateOfMeasure", column = "b.dateOfMeasure")
                }
            ),
            @EntityResult(
                    entityClass = Component.class,
                    fields = {
                        @FieldResult(name = "id", column = "c.id"),
                        @FieldResult(name = "componentSerialNumber", column = "c.componentSerialNumber"),
                        @FieldResult(name = "componentMeasure", column = "c.ComponentMeasure")
                    }
            )
        }
    )

then I mapped the query to the JPA repository defined for Device:然后我将查询映射到为 Device 定义的 JPA 存储库:

@Query(nativeQuery = true, name="Device.getMeasuresAndDates") 
public List<Object> LetturePerPod(@Param("device") String device);

First, I'm not sure what type has to be returned by the interface method.首先,我不确定接口方法必须返回什么类型。 Second, I do not know if it's correct to define such a method in the interface.其次,我不知道在接口中定义这样的方法是否正确。 But if I want to define the method directly in the entity class, I have to access the EntityManager to use the @NamedNativeQuery, but that is not possible from within the class.但是如果我想直接在实体类中定义方法,我必须访问 EntityManager 才能使用@NamedNativeQuery,但这在类中是不可能的。 I aim to keep the architecture as clean as possible, leveraging JPA and avoiding any tricky solutions.我的目标是保持架构尽可能干净,利用 JPA 并避免任何棘手的解决方案。

Anyway, doing things this way I get this error:无论如何,以这种方式做事我得到这个错误:

Cannot createTypedQuery for query with more than one return

I guess it would work only if I return all fields of all entities, like我想只有当我返回所有实体的所有字段时它才会起作用,比如

select
a.*,
b.*,
c.*
from

so which is the right approach to the problem?那么哪个是解决问题的正确方法?

Any suggestions are appreciated任何建议表示赞赏

It looks like that it's your column "id" which is duplicated in a and c.看起来这是您的列“id”,它在 a 和 c 中重复。 Just like in sql you could just add an alias to the duplicated columns.就像在 sql 中一样,您可以为重复的列添加别名。

@NamedNativeQuery(
    name = "Device.getMeasuresAndDates",
    query = """
    select a.id as aid, 
    a.device,
    a.deviceManufacturer, 
    b.dateOfMeasure, 
    c.Id as cid, 
    c.componentSerialNumber, 
    c.ComponentMeasure
    from devices a inner join measures b on b.device_id = a.id
    inner join instruments c on c.id = b.instrument_id
    where a.device = :device
    order by b.dateOfMeasure, c.componentSerialNumber
    """,
    resultSetMapping = "MeasuresAndDatesMapping"
    )

PS: SQL doesn't care about uppercase Id and ID and id is the exact same field. PS:SQL 不关心大写的 Id 和 ID 和 id 是完全相同的字段。

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

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