Перевести SQL Запрос в JPQL - @ManyToMany join - PullRequest
0 голосов
/ 27 апреля 2020

Я пытаюсь перевести SQL использование собственного запроса в аннотации @Query ("...", native = true) Spring Data Jpa для использования запроса JPQL в той же аннотации. SQL Запрос:

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);

А вот переведено SQL из JPQL.

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) но ТОЛЬКО ДЛЯ ПЕРВОГО ОБЪЕКТА. 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": "james@gmail.com",
        "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": "james@gmail.com",
        "doctorId": 1,
        "doctorTitle": "dr n. md."
    }
]

Я попытался использовать переведенный запрос SQL с использованием JPQL в Workbench, потому что я использую базу данных MySQL, и результат тот же - первый объект правильно, а остальные имеют нулевые значения внутри сопоставленных столбцов @ManyToMany. Вот мои классы Entity, если бы этот вопрос был немного проще:

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. Это вообще возможно? Пожалуйста, помогите мне ...

1 Ответ

0 голосов
/ 27 апреля 2020

У вас есть несколько ошибок в вашем запросе. Вместо этого используйте следующее

@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);
...