如何使用 Jpa 查询在 1 个 DTO 中加入 4 个表
How to join 4 tables in 1 DTO with Jpa Query
所以我有 4 张桌子
雇主
@Entity
@EqualsAndHashCode(callSuper = false)
@Table(name = "employers")
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler", "jobPostings"})
@PrimaryKeyJoinColumn(name="employer_id", referencedColumnName = "id")
public class Employer extends User {
@Column(name = "company_name")
private String companyName;
@Column(name = "website")
private String website;
@Column(name = "phone_number")
private String phoneNumber;
@OneToMany(mappedBy="employer")
private List<JobPosting> jobPostings;
}
一个城市
@Data
@Entity
@Table(name="cities")
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler", "jobPostings"})
public class City {
@Id
@Column(name="id")
private int id;
@Column(name="city_name")
private String cityName;
@OneToMany(mappedBy="city")
private List<JobPosting> jobPostings;
}
一个职位
@AllArgsConstructor
@Data
@Entity
@Table(name="job_positions")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler", "jobPostings"})
public class JobPosition {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="job_position_id")
private int id;
@Column(name="title")
private String title;
@OneToMany(mappedBy="jobPosition")
private List<JobPosting> jobPostings;
}
还有一个 JobPosting(如招聘广告)
@Entity
@Table(name="job_postings")
@Data
@NoArgsConstructor
@AllArgsConstructor
//@JsonIgnoreProperties({"hibernateLazyInitializer", "handler", "city", "jobPosition","employer"})
public class JobPosting {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private int id;
@Column(name="job_requirements")
private String jobRequirements;
@Column(name="salary_min")
private int salaryMin;
@Column(name="salary_max")
private int salaryMax;
@Column(name="application_deadline")
private LocalDate applicationDeadline;
@Column(name="number_of_openings")
private int numberOfOpenings;
@Column(name="stream_date")
private LocalDate streamDate;
@ManyToOne()
@JoinColumn(name="city_id")
private City city;
@ManyToOne()
@JoinColumn(name="job_position_id")
private JobPosition jobPosition;
@ManyToOne()
@JoinColumn(name= "employer_id")
private Employer employer;
}
我已经为它们全部实现了必要的映射,并且工作正常。
但是,我想加入他们的 DTO,例如:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class JobPostingWithJobPositionCityEmployerDto {
private int id;
private String jobRequirements;
private int salaryMin;
private int salaryMax;
private LocalDate applicationDeadline;
private int numberOfOpenings;
private LocalDate streamDate;
private String cityName;
private String title;
private String companyName;
}
为了以更干净的方式获取我想要的字段,我正在尝试使用 springframework.jpa 的 @Query 注释,但我无法完全管理它,因为我刚刚了解到这个,我正在使用的查询是:
@Query(value ="Select new kodlamaio.hrms.entities.dtos.JobPostingWithJobPositionCityEmployerDto"
+ "(j.id, j.jobRequirements, j.salaryMin, j.salaryMax, j.numberOfOpenings, j.streamDate, j.applicationDeadline, c.cityName, p.title, e.companyName)"
+ " From Employer e Inner Join e.jobPostings j, "
+ "From City c Inner Join c.jobPostings j, "
+ "From JobPosition p Inner Join p.jobPostings j", nativeQuery = true)
List<JobPostingWithJobPositionCityEmployerDto> getJobPostings();
我什至不知道这是否是正确的方法,我不断收到语法错误,我查找了答案但无法完全理解他们在说什么,有很多不同的场景。
因此,如果有人可以帮助我完成此查询并推荐一些资源来了解不同的命令,我将不胜感激,在此先感谢。
在查询中使用 new
关键字将查询结果映射到 DTO 仅适用于 JPQL,它不适用于 SQL(您正在使用的)。
在我看来,如果您尝试编写过于复杂的查询,因为所有内容都可以通过 JobPosting
class achieved/reached,这将在使用时隐式执行连接JPQL.
因此,而不是您的原生 SQL 编写 JPQL 应该可以修复它。
类似
@Query(value ="Select new kodlamaio.hrms.entities.dtos.JobPostingWithJobPositionCityEmployerDto"
+ "(jp.id, jp.jobRequirements, jp.salaryMin, jp.salaryMax, jp.numberOfOpenings, jp.streamDate, jp.applicationDeadline, jp.city.cityName, jp.jobPosition.title, jp. employer.companyName)"
+ " From JobPosting jp)
哪个应该可以解决问题。您的 JPA 提供程序应该足够聪明,能够确定要加入和检索的内容。
通常这被命名为 Projection,我相信您已经创建了 JobPostingWithJobPositionCityEmployerDto
,其中包含 10 个参数的构造函数,当然还有它们各自的数据类型。由于它是 jpa 的习惯,因此您不能使用 nativeQuery = true
。这些修改应该没问题。
@vlad-mihalcea 来救援
https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/
所以我有 4 张桌子
雇主
@Entity
@EqualsAndHashCode(callSuper = false)
@Table(name = "employers")
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler", "jobPostings"})
@PrimaryKeyJoinColumn(name="employer_id", referencedColumnName = "id")
public class Employer extends User {
@Column(name = "company_name")
private String companyName;
@Column(name = "website")
private String website;
@Column(name = "phone_number")
private String phoneNumber;
@OneToMany(mappedBy="employer")
private List<JobPosting> jobPostings;
}
一个城市
@Data
@Entity
@Table(name="cities")
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler", "jobPostings"})
public class City {
@Id
@Column(name="id")
private int id;
@Column(name="city_name")
private String cityName;
@OneToMany(mappedBy="city")
private List<JobPosting> jobPostings;
}
一个职位
@AllArgsConstructor
@Data
@Entity
@Table(name="job_positions")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler", "jobPostings"})
public class JobPosition {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="job_position_id")
private int id;
@Column(name="title")
private String title;
@OneToMany(mappedBy="jobPosition")
private List<JobPosting> jobPostings;
}
还有一个 JobPosting(如招聘广告)
@Entity
@Table(name="job_postings")
@Data
@NoArgsConstructor
@AllArgsConstructor
//@JsonIgnoreProperties({"hibernateLazyInitializer", "handler", "city", "jobPosition","employer"})
public class JobPosting {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private int id;
@Column(name="job_requirements")
private String jobRequirements;
@Column(name="salary_min")
private int salaryMin;
@Column(name="salary_max")
private int salaryMax;
@Column(name="application_deadline")
private LocalDate applicationDeadline;
@Column(name="number_of_openings")
private int numberOfOpenings;
@Column(name="stream_date")
private LocalDate streamDate;
@ManyToOne()
@JoinColumn(name="city_id")
private City city;
@ManyToOne()
@JoinColumn(name="job_position_id")
private JobPosition jobPosition;
@ManyToOne()
@JoinColumn(name= "employer_id")
private Employer employer;
}
我已经为它们全部实现了必要的映射,并且工作正常。 但是,我想加入他们的 DTO,例如:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class JobPostingWithJobPositionCityEmployerDto {
private int id;
private String jobRequirements;
private int salaryMin;
private int salaryMax;
private LocalDate applicationDeadline;
private int numberOfOpenings;
private LocalDate streamDate;
private String cityName;
private String title;
private String companyName;
}
为了以更干净的方式获取我想要的字段,我正在尝试使用 springframework.jpa 的 @Query 注释,但我无法完全管理它,因为我刚刚了解到这个,我正在使用的查询是:
@Query(value ="Select new kodlamaio.hrms.entities.dtos.JobPostingWithJobPositionCityEmployerDto"
+ "(j.id, j.jobRequirements, j.salaryMin, j.salaryMax, j.numberOfOpenings, j.streamDate, j.applicationDeadline, c.cityName, p.title, e.companyName)"
+ " From Employer e Inner Join e.jobPostings j, "
+ "From City c Inner Join c.jobPostings j, "
+ "From JobPosition p Inner Join p.jobPostings j", nativeQuery = true)
List<JobPostingWithJobPositionCityEmployerDto> getJobPostings();
我什至不知道这是否是正确的方法,我不断收到语法错误,我查找了答案但无法完全理解他们在说什么,有很多不同的场景。 因此,如果有人可以帮助我完成此查询并推荐一些资源来了解不同的命令,我将不胜感激,在此先感谢。
在查询中使用 new
关键字将查询结果映射到 DTO 仅适用于 JPQL,它不适用于 SQL(您正在使用的)。
在我看来,如果您尝试编写过于复杂的查询,因为所有内容都可以通过 JobPosting
class achieved/reached,这将在使用时隐式执行连接JPQL.
因此,而不是您的原生 SQL 编写 JPQL 应该可以修复它。
类似
@Query(value ="Select new kodlamaio.hrms.entities.dtos.JobPostingWithJobPositionCityEmployerDto"
+ "(jp.id, jp.jobRequirements, jp.salaryMin, jp.salaryMax, jp.numberOfOpenings, jp.streamDate, jp.applicationDeadline, jp.city.cityName, jp.jobPosition.title, jp. employer.companyName)"
+ " From JobPosting jp)
哪个应该可以解决问题。您的 JPA 提供程序应该足够聪明,能够确定要加入和检索的内容。
通常这被命名为 Projection,我相信您已经创建了 JobPostingWithJobPositionCityEmployerDto
,其中包含 10 个参数的构造函数,当然还有它们各自的数据类型。由于它是 jpa 的习惯,因此您不能使用 nativeQuery = true
。这些修改应该没问题。
@vlad-mihalcea 来救援 https://vladmihalcea.com/the-best-way-to-map-a-projection-query-to-a-dto-with-jpa-and-hibernate/