在JPA查询中包含枚举

时间:2017-03-18 15:55:45

标签: java spring hibernate jpa enums

我有一个以下表格的课程。

@Entity
public class Person{
    public enum SEX {
      MALE, FEMALE, OTHER
    }

    private String name;
    private SEX sex;
 }

我有一个扩展JpaRepostory的接口类。枚举在查询中不起作用。我正在尝试使用Spring JPA来获取数据。

public interface PersonRepository extends JpaRepository<Person, Long> {


    @Query("SELECT p FROM Person p WHERE 
            "p.SEX = com.example.Person.Sex.MALE " +
            "AND p.name = :name")
    public List<Person> checkName(@Param("name") String name,);

}

我收到以下异常

Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Invalid path: 'com.example.Person.Sex.MALE'

我该如何解决?

2 个答案:

答案 0 :(得分:5)

您不尊重您的课程和属性的情况。它应该是

p.sex = com.example.Person.SEX.MALE

答案 1 :(得分:0)

除了已经提到的案例错误之外,还有另一个问题:您的枚举类是一个嵌套类。第三个问题是 Hibernate 似乎有大写类名的问题,即您需要将类名从 SEX 更改为 Sex

变体 1:

将枚举定义为包 com.example 中的顶级类

package com.example;
public enum Sex {
    MALE, FEMALE, OTHER
}

然后您可以使用例如从存储库访问枚举值com.example.Sex.MALE

@Repository
public interface PersonRepository extends JpaRepository<Person, Long> {

    @Query("SELECT p FROM Person p WHERE " + 
            "p.sex = com.example.Sex.MALE " +
            "AND p.name = :name")
    public List<Person> checkName(@Param("name") String name);

}

令人惊讶的是(错误?)如果您将枚举的名称从 Sex 更改为 SEX(同时明显调整查询中的名称),这最终会导致错误。

变体 2:

您可以将 Sex 的定义保留为嵌套类。然后将枚举编译为名称为 Person$Sex.class 的类。只需在查询字符串中使用此名称:

@Entity
public class Person {

    public enum Sex {
        MALE, FEMALE, OTHER
    }

    @Id @GeneratedValue long id;
    private String name;
    private Sex sex;
    
    public Person() {}
    public Person(String name, Sex sex) {
        this.name = name;
        this.sex = sex;
    }
}

然后需要将存储库编写为

public interface PersonRepository extends JpaRepository<Person, Long> {

    @Query("SELECT p FROM Person p WHERE " + 
            "p.sex = com.example.Person$Sex.MALE " +
            "AND p.name = :name")
    public List<Person> checkName(@Param("name") String name);

}

再一次,如果您将嵌套类的名称从 Sex 更改为 SEX(也在查询字符串中),则文本异常

Invalid path: 'com.example.Person$SEX.MALE' 
   [SELECT p FROM com.example.Person p WHERE p.sex = com.example.Person$SEX.MALE 
                                                             AND p.name = :name]

被抛出,尽管生成的字节码存储在类 Person$SEX.class 中。