在JPA查询中包含枚举类型

5

我有一个以下形式的类。

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

    private String name;
    private SEX sex;
 }

我有一个继承了JpaRepository的接口类。在查询中枚举类型无法工作。我正在尝试使用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' 我该如何解决它?此异常表示路径无效,可能是因为在查询中使用了错误的语法或拼写错误。请检查查询并确保路径正确且与数据库模型匹配。

返回翻译后的文本:或者使用参数并将其设置为枚举值。 - Neil Stockton
2
你的枚举应该命名为SEX,而不是Sex。你在Person类中的性别属性应该命名为sex,而不是SEX。 - JB Nizet
2
请遵循Java命名规范,这实际上有助于防止错误。 - Lew Bloch
你是如何在实体类中映射性别列的?性别的数据库列类型是什么? - surya
2个回答

12

你没有遵守类和属性的大小写规范。应该是:

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

在Hibernate 6中怎么样?现在它不再像这样工作了。 - undefined

1
除了已经提到的案例错误之外,还有另一个问题:你的枚举类是一个嵌套类。第三个问题是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 中,但仍会抛出异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接