在 mysql table 休眠中对枚举列执行条件查询时出错

Getting error while executing criteria query on enum column in mysql table hibernate

这是代码:

Session session = sessionFactory.getCurrentSession();
Criteria criteria = session.createCriteria(Contact.class)
    .add(Restrictions.like("gender", "male", MatchMode.ANYWHERE)));
List<Object[]> contactList = criteria.list();

其中性别是 Contact.java

中的枚举类型列
@Entity
@Table(name = "contact_master")
public class Contact {

      public enum Gender {
           MALE,FEMALE
      }

      @Column(name = "gender")
      @Enumerated(EnumType.STRING)
      private Gender gender;

      public Gender getGender() {
         return gender;
      }

      public void setGender(Gender gender) {
          this.gender = gender;
      }

}

当我在上面的代码中 运行 时出现异常,例如:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Enum

在单独的文件中定义您的枚举,以便您可以从任何地方访问它,然后像这样使用它:

Criteria criteria = session.createCriteria(Contact.class)
   .add(Restrictions.like("gender", Gender.MALE, MatchMode.ANYWHERE)));

编辑 1

正如您指定的那样,如果值是动态的,那么您可以在枚举中定义这样的函数。

public enum Gender {
    MALE,FEMALE;

    public static Gender getGender(String strGender) {
        if(strGender.equalsIgnoreCase("m") | strGender.equalsIgnoreCase("ma") | strGender.equalsIgnoreCase("male")) 
            return Gender.MALE;

        if(strGender.equalsIgnoreCase("f") | strGender.equalsIgnoreCase("fema") | strGender.equalsIgnoreCase("female")) 
            return Gender.FEMALE;

        return null;
    }
}

然后您可以像这样使用它们:

Criteria criteria = session.createCriteria(Contact.class)
   .add(Restrictions.like("gender", Gender.getGender("fema"), MatchMode.ANYWHERE)));

您可以定义映射到同一列的另一个 String 类型的不可插入和不可更新的字段:

@Entity
@Table(name = "contact_master")
public class Contact {

      public enum Gender {
           MALE,FEMALE
      }

      @Column(name = "gender")
      @Enumerated(EnumType.STRING)
      private Gender gender;

      @Column(name = "gender", insertable = false, updatable = false)
      private String genderAsText;

      public Gender getGender() {
         return gender;
      }

      public void setGender(Gender gender) {
          this.gender = gender;
      }
}

您不需要它的 getter 和 setter,您只能在需要将 gender 视为纯文本的查询中使用它:

Criteria criteria = session.createCriteria(Contact.class)
    .add(Restrictions.ilike("genderAsText", "male", MatchMode.ANYWHERE)));

请注意,我还使用了 Restrictions.ilike 方法,因为您可能希望比较不区分大小写。

如果你考虑一下你正在尝试做什么,枚举列的部分匹配,休眠真的没有意义。

您已经告诉 hibernate 性别是一个枚举,并且只有两个允许的值 - MALE 或 FEMALE。所以这些是唯一可能的值 hibernate expects/allows。看起来您只能使用限制 class 对枚举类型的精确匹配查询枚举。

但是您可以在不更改实体模型的情况下使用如下查询来执行此操作。所以如果你传入 "f" 或 "fem" 它只会给你女性,但大多数其他组合都会 return 所有男性的所有字母也会在女性中 - 你显然可以改变它的方式生成 like 参数,因此您可以匹配 m%、ma%、mal% 以查找 MALE,或匹配 f%、fe% 等以查找 FEMALE。

@GetMapping(value = "/list/{queryParam}")
public ResponseEntity<List<Contact>> list(@PathVariable String queryParam ) {
    Session session = entityManager.unwrap(Session.class);
    SQLQuery query = session.createSQLQuery("select id, gender from contact_master where gender like :param");
    query.setParameter("param", "%"+queryParam.toUpperCase()+"%");
    final List<Contact> list = query.list();

    return ResponseEntity.ok(list);
}

希望对您有所帮助

试试这个(假设目的是只 return 男性联系人):

Criteria criteria = session.createCriteria(Contact.class)
    .add(Restrictions.eq("gender", Contact.Gender.MALE));