将SQL查询翻译成JPQL - @多对多 join

问题描述 投票:0回答:1

我试图将@Query("...", native=true)Spring Data Jpa注解中的SQL原生查询用法翻译成JPQL在同一个注解中的查询用法.SQL Query。

select d.id as doctorId, d.firstName as doctorFirstName, d.lastName as doctorLastName, d.title as doctorTitle, 
d.email as doctorEmail, v.id as id, v.dateFrom as dateFrom, v.dateTo as dateTo, v.status as status,
md.id as medicalServicesId, md.service as medicalServicesService, md.price as medicalServicesPrice 
from Visit v 
left outer join Doctor d on v.doctor_id=d.id 
left outer join visit_medical_services vms on v.id=vms.medical_services_id 
left outer join MedicalService md on vms.visit_id=md.id 
where d.id= :doctorId and v.status= :status and v.dateFrom>= :dateFrom and v.dateTo<= :dateTo

我使用的是Spring Projected Interface, 这就是为什么列的别名是这样命名的.

现在我想用JPQL得到完全相同的结果--项目列表。我试过的是这样的。

    @Query("select d.id as doctorId, d.firstName as doctorFirstName, d.lastName as doctorLastName, d.title as doctorTitle, d.email as doctorEmail, " +
            "v.id as id, v.dateFrom as dateFrom, v.dateTo as dateTo, v.status as status, md.id as medicalServicesId, md.service as medicalServicesService, md.price as medicalServicesPrice \n" +
            "from Visit v \n" +
            "left outer join Doctor d on v.doctor.id=d.id \n" +
            "left outer join v.medicalServices vms on vms.id=v.id \n" +
            "left outer join MedicalService md on md.id=vms.id \n" +
            "where d.id= :doctorId and v.status= :status and v.dateFrom>= :dateFrom and v.dateTo<= :dateTo")
    List<VisitInfoWithPatientAndMedServices3joins> getAllVisitInfoWithPatientAndMedicalServicesJpqlQuery
    (@Param("doctorId") Long doctorId, @Param("status") VisitStatus status, @Param("dateFrom") LocalDateTime dateFrom, @Param("dateTo") LocalDateTime dateTo, Pageable pageable);

这是从JPQL翻译过来的SQL

select doctor1_.id as col_0_0_, doctor1_.firstName as col_1_0_, doctor1_.lastName as col_2_0_, doctor1_.title as col_3_0_, doctor1_.email as col_4_0_, visit0_.id as col_5_0_, visit0_.dateFrom as col_6_0_, visit0_.dateTo as col_7_0_, visit0_.status as col_8_0_, medicalser4_.id as col_9_0_, medicalser4_.service as col_10_0_, medicalser4_.price as col_11_0_ 
from Visit visit0_ 
left outer join  
(visit_medical_services medicalser2_ left outer join MedicalService medicalser3_ on medicalser2_.visit_id=medicalser3_.id) on visit0_.id=medicalser2_.medical_services_id 
and (medicalser3_.id=visit0_.id) 
left outer join Doctor doctor1_ on (visit0_.doctor_id=doctor1_.id) 
left outer join MedicalService medicalser4_ on (medicalser4_.id=medicalser3_.id) where doctor1_.id=? and visit0_.status=? and visit0_.dateFrom>=? and visit0_.dateTo<=? limit ?

这里的问题是,它从@ManyToMany关系(visit_medical_services)中返回列,但只针对第一个对象。下面是Postman的Json响应。

[
    {
        "id": 1,
        "status": "PAID",
        "dateFrom": "2019-04-10T08:00:00",
        "dateTo": "2019-04-10T08:30:00",
        "medicalServicesId": 1,
        "medicalServicesService": "Visit",
        "medicalServicesPrice": 100.0,
        "doctorLastName": "James",
        "doctorFirstName": "Alex",
        "doctorEmail": "[email protected]",
        "doctorId": 1,
        "doctorTitle": "dr n. md."
    },
    {
        "id": 2,
        "status": "PAID",
        "dateFrom": "2019-04-10T09:00:00",
        "dateTo": "2019-04-10T09:30:00",
        "medicalServicesId": null,
        "medicalServicesService": null,
        "medicalServicesPrice": null,
        "doctorLastName": "James",
        "doctorFirstName": "Alex",
        "doctorEmail": "[email protected]",
        "doctorId": 1,
        "doctorTitle": "dr n. md."
    }
]

我试着在Workbench中使用JPQL翻译SQL查询,因为我使用的是MySQL数据库,结果是一样的--第一个对象是正确的,其余的对象在映射的@ManyToMany列中都是空值。

public class Visit {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
    LocalDateTime dateFrom;
    LocalDateTime dateTo;
    @Enumerated(EnumType.STRING)
    VisitStatus status;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "doctor_id", referencedColumnName = "id", nullable = true)
    @JsonManagedReference
    Doctor doctor;
    @ManyToOne(fetch = FetchType.LAZY)
    @JsonManagedReference
    @JoinColumn(name = "patient_id", referencedColumnName = "id", nullable = true)
    Patient patient;
    @ManyToMany
    @JsonManagedReference
    @JoinTable(
            name = "visit_diseases",
            joinColumns = @JoinColumn(
                    name = "disease_id", referencedColumnName = "id"),
            inverseJoinColumns = @JoinColumn(
                    name = "visit_id", referencedColumnName = "id"))
    List<Disease> diseases;
    @ManyToMany
    @JsonManagedReference
    @JoinTable(
            name = "visit_medical_services",
            joinColumns = @JoinColumn(
                    name = "medical_services_id"),
            inverseJoinColumns = @JoinColumn(
                    name = "visit_id"))
    Set<MedicalService> medicalServices;
    String mainSymptoms;
    String treatment;
    String allergy;
    String addiction;
    String comment;
}

还有医疗服务

public class MedicalService {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    Long id;
    String service;
    Float price;

    @ManyToMany(mappedBy = "medicalServices", fetch = FetchType.EAGER)
    private Set<Visit> visits;

    public MedicalService(Long id, String service, float price) {
        this.id = id;
        this.service = service;
        this.price = price;
    }
}

谁能看一下,并向我解释一下这里有什么不正确的地方?我想实现的是让JPQL生成 同样的 SQL查询。它甚至可能吗?请帮助我...

sql spring hibernate spring-data-jpa jpql
1个回答
0
投票

你的查询中存在一些错误。请使用以下内容代替

@Query("select d.id as doctorId, d.firstName as doctorFirstName, d.lastName as doctorLastName, d.title as doctorTitle, d.email as doctorEmail, " +
        "v.id as id, v.dateFrom as dateFrom, v.dateTo as dateTo, v.status as status, md.id as medicalServicesId, md.service as medicalServicesService, md.price as medicalServicesPrice \n" +
        "from Visit v \n" +
        "left outer join v.doctor d \n" +
        "left outer join v.medicalServices md \n"
        "where d.id= :doctorId and v.status= :status and v.dateFrom>= :dateFrom and v.dateTo<= :dateTo")
List<VisitInfoWithPatientAndMedServices3joins> getAllVisitInfoWithPatientAndMedicalServicesJpqlQuery
(@Param("doctorId") Long doctorId, @Param("status") VisitStatus status, @Param("dateFrom") LocalDateTime dateFrom, @Param("dateTo") LocalDateTime dateTo, Pageable pageable);
© www.soinside.com 2019 - 2024. All rights reserved.