【发布时间】:2020-08-10 19:44:06
【问题描述】:
我正在尝试将 @Query("...", native=true) Spring Data Jpa 注释中的 SQL 本机查询用法转换为同一注释中的 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,这就是为什么列别名被命名为 like this。
现在我想用 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": "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."
}
]
我尝试在 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 生成 THE SAME SQL 查询。甚至有可能吗?请帮帮我...
【问题讨论】:
-
是否可以通过打开 show-sql 来共享控制台中生成的 jpql gtting 的等效 sql 查询?
-
当然,我刚刚编辑了问题,在 JPQL @Query 下面你可以看到生成的 SQL。
标签: sql spring hibernate spring-data-jpa jpql