在 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));
这是代码:
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));