Spring JPA 和 Hibernate 的 JPQL 查询错误

Posted

技术标签:

【中文标题】Spring JPA 和 Hibernate 的 JPQL 查询错误【英文标题】:JPQL Query error with Spring JPA and Hibernate 【发布时间】:2019-10-27 20:32:32 【问题描述】:

我正在尝试获取与特定人员相关的所有技能。

在我的 Spring Boot 应用程序中尝试使用 JPQL 从 mysql DB 获取数据时出现以下错误:

org.hibernate.QueryException: 无法解析属性: person_skill of: com.skilltrack.app.Domain.Skill [SELECT s FROM com.skilltrack.app.Domain.Skill s JOIN s.person_skill ps WHERE ps.fk_person = ?1]

这是我的代码:

Person.java

@Data
@EqualsAndHashCode(exclude = "personCourses")
@Entity(name = "person")
@Table(name = "person")
public class Person implements Serializable 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer person_id;

    @NotBlank
    private String name;

    @NotBlank
    private String surname;

    @NotBlank
    private String email;

    @NotBlank
    private String password;

    @NotBlank
    private String personType; //admin or user

    @JsonIgnore
    @ManyToMany  // this mapping is referred to in the Course class
    @JoinTable(name = "person_course",
            joinColumns = @JoinColumn(name = "fk_person", referencedColumnName = "person_id"),
            inverseJoinColumns = @JoinColumn(name = "fk_course", referencedColumnName = "course_id"))
    private List<Course> personCourses;

    @JsonIgnore
    @ManyToMany  // this mapping is referred to in the Skill class
    @JoinTable(name = "person_skill",
            joinColumns = @JoinColumn(name = "fk_person", referencedColumnName = "person_id"),
            inverseJoinColumns = @JoinColumn(name = "fk_skill", referencedColumnName = "skill_id"))
    private List<Skill> personSkills;

课程.java

@Data
@EqualsAndHashCode(exclude = "skills")
@Entity(name = "course")
@Table(name = "course")
public class Course 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer course_id;

    @NotBlank
    private String name;

    @NotBlank
    private String description;

    @JsonIgnore
    @ManyToMany(mappedBy = "courses") // mapping defined in Skill already
    private List<Skill> skills;

    @NotBlank
    private Boolean completed; // 0 no 1 yes

    @JsonIgnore
    @ManyToMany(mappedBy = "personCourses")
    private List<Person> coursePerson;

技能.java

@Data
@EqualsAndHashCode(exclude = "courses")
@Entity(name = "skill")
@Table(name = "skill")
public class Skill 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer skill_id;

    @NotBlank
    private String name;

    @NotBlank
    private String description;

    @JsonIgnore
    @ManyToMany(cascade = CascadeType.ALL)  // this mapping is referred to in the Course class
    @JoinTable(name = "course_skills",
            joinColumns = @JoinColumn(name = "fk_skill", referencedColumnName = "skill_id"),
            inverseJoinColumns = @JoinColumn(name = "fk_course", referencedColumnName = "course_id"))
    private List<Course> courses;

    @JsonIgnore
    @ManyToMany(mappedBy = "personSkills")
    private List<Person> skill_person;

PersonRepository.java

@Repository
public interface PersonRepository extends JpaRepository<Person, Integer> 

    @Query(value =
            "SELECT s " +
            "FROM skill s JOIN s.person_skill ps " +
            "WHERE ps.fk_person = ?1 ")
    List<Skill> getPersonSkills(Integer personID);



The issue is with the JPQL statement:
"SELECT s FROM skill s JOIN s.person_skill ps WHERE ps.fk_person = ?1 "

I have tried the following variations:

"SELECT s FROM skill s INNER JOIN s.person_skill ps WHERE ps.fk_person = ?1"

"SELECT s FROM skill s JOIN FETCH s.person p WHERE ps.fk_person = ?1"

"SELECT s FROM skill s JOIN s.person p JOIN s.person_skill ps WHERE ps.fk_person = ?1"

"SELECT s FROM skill s JOIN person p JOIN person_skill ps WHERE ps.fk_person = ?1"

我应该如何更改我的 JPQL 查询以返回与特定人员相关的技能列表?

【问题讨论】:

Skill 只有字段skill_person 【参考方案1】:

将您输入错误的实体名称从person_skill 更改为Skill.java 中定义的skill_person

【讨论】:

我做到了,修复了错误,但现在它返回了与技能 ID 相关的所有人。大声笑......请停下来【参考方案2】:

您有此错误 org.hibernate.QueryException 因为您在 JPQL 中的字段名称错误。 技能实体的字段名称为:skill_person。 您的 JPQL 查询中有另一个字段名称:person_skill

【讨论】:

我做到了,修复了错误,但现在它返回了与技能 ID 相关的所有人。哈哈 试试这个查询 - “SELECT s FROM Skill s JOIN s.skill_person p WHERE p.person_id = ?1”【参考方案3】:

无需编写自定义查询即可获得结果。 Spring 默认构建诸如“skills”和“persons”之类的端点,使用时,它们会显示其他端点,例如“http://localhost:8080/skills/id/skill_person”

玩弄这些将导致您找到任何结果组合。 这是可能的,因为多对多映射是双向定义的,就像您在当前项目中的方式一样,而且 spring 很棒。

【讨论】:

谢谢。是的,当您正确命名所有内容时,JPA 命名约定确实是您所需要的。

以上是关于Spring JPA 和 Hibernate 的 JPQL 查询错误的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA 和 Hibernate

Spring Hibernate JPA 联表查询

Spring Hibernate JPA 联表查询 复杂查询

spring-data-jpa+hibernate 各种缓存的配置演示

使用 JPA 和 Spring 加载选定的 Hibernate 实体

Spring、Spring Security、JPA、MySQL、Hibernate 配置