You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JPA多表原生查询仅返回单表数据,如何获取全量数据用于Jasper报表

问题根因

你当前Repository方法的返回类型为List<Dispense>,JPA原生查询仅会将查询结果映射到返回类型对应实体的字段,因此即便SQL拉取了4个表的全量数据,最终也只会保留Dispense表对应的字段值。

解决方案

方案1:使用接口投影(实现最简单,无需额外复杂配置)

首先定义一个投影接口,包含你需要的四个表所有字段的getter方法,示例如下:

public interface InvoiceProjection {
    // patient表对应字段的getter
    Long getPatientId();
    String getPatientName();
    // 其余需要的patient字段自行补充

    // consult表对应字段的getter
    Long getConsultId();
    java.util.Date getConsultTime();
    // 其余需要的consult字段自行补充

    // script表对应字段的getter
    Long getScriptId();
    String getScriptContent();
    // 其余需要的script字段自行补充

    // dispense表对应字段的getter
    Long getDispenseId();
    String getIcd10();
    String getTariffCode();
    String getDispenseItem();
    java.math.BigDecimal getPrice();
}

修改Repository方法的返回类型为该投影接口:

@Query(
    value = "SELECT p.*, c.*, s.*, d.* from patient p, consult c ,script s,dispense d "
            + " where p.patient_id=c.patient_id "
            + " and c.consult_id = d.consult_id " 
            + " and c.fk_script_id =s.script_id"
            + " and c.consult_id=?1 ", 
    nativeQuery = true
)
List<InvoiceProjection> findInvoiceByConsultId(Long consultId);

最后修改Controller的返回类型即可:

@RequestMapping(value = "/api/invoice/{consultId}",method = {RequestMethod.GET}) 
public List<InvoiceProjection> invoice(@PathVariable(value="consultId")Long consultId){
    return dispenseRepository.findInvoiceByConsultId(consultId);
}

方案2:使用@SqlResultSetMapping自定义POJO映射(更适合Jasper报表开发,结构稳定兼容性好)

首先定义包含所有需要字段的DTO类,添加全参构造函数:

public class InvoiceDTO {
    // 依次定义patient、consult、script、dispense需要的字段
    private Long patientId;
    private String patientName;
    private Long consultId;
    private Long scriptId;
    private Long dispenseId;
    private String icd10;
    private String tariffCode;
    private String dispenseItem;
    private java.math.BigDecimal price;
    // 其余需要的字段自行补充

    // 全参构造函数,参数顺序要和SQL查询返回的字段顺序完全一致
    public InvoiceDTO(Long patientId, String patientName, Long consultId, Long scriptId, Long dispenseId, String icd10, String tariffCode, String dispenseItem, java.math.BigDecimal price) {
        this.patientId = patientId;
        this.patientName = patientName;
        this.consultId = consultId;
        this.scriptId = scriptId;
        this.dispenseId = dispenseId;
        this.icd10 = icd10;
        this.tariffCode = tariffCode;
        this.dispenseItem = dispenseItem;
        this.price = price;
    }
    // 补充所有字段的getter方法
}

在任意一个JPA实体类上添加结果集映射配置(可以直接加在现有Dispense实体类上):

@SqlResultSetMapping(
    name = "InvoiceMapping",
    classes = @ConstructorResult(
        targetClass = InvoiceDTO.class,
        columns = {
            // 这里的column顺序、类型要和SQL查询返回的字段顺序、类型完全匹配,name为SQL返回的数据库字段名
            @ColumnResult(name = "patient_id", type = Long.class),
            @ColumnResult(name = "patient_name", type = String.class),
            @ColumnResult(name = "consult_id", type = Long.class),
            @ColumnResult(name = "script_id", type = Long.class),
            @ColumnResult(name = "dispense_id", type = Long.class),
            @ColumnResult(name = "icd10", type = String.class),
            @ColumnResult(name = "tariff_code", type = String.class),
            @ColumnResult(name = "dispense_item", type = String.class),
            @ColumnResult(name = "price", type = java.math.BigDecimal.class)
            // 其余需要的字段按顺序补充
        }
    )
)
@Entity
public class Dispense {
    // 原有Dispense实体的代码保持不变
}

修改Repository方法,指定结果集映射:

@Query(
    value = "SELECT p.*, c.*, s.*, d.* from patient p, consult c ,script s,dispense d "
            + " where p.patient_id=c.patient_id "
            + " and c.consult_id = d.consult_id " 
            + " and c.fk_script_id =s.script_id"
            + " and c.consult_id=?1 ", 
    nativeQuery = true,
    resultSetMapping = "InvoiceMapping"
)
List<InvoiceDTO> findInvoiceByConsultId(Long consultId);

最后修改Controller返回类型为List<InvoiceDTO>即可。

方案3:返回List<Object[]>(仅适合临时调试,不推荐正式使用)

直接修改Repository返回类型为List<Object[]>,查询返回的每个Object数组按SQL字段顺序存储四个表的字段值,可自行遍历封装成需要的结构,但可读性和维护性差,不适合正式业务场景。

内容的提问来源于stack exchange,提问作者hoosain.madhi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 17:45:03