Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

This is the code :

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

Where gender is enum type column in 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;
      }

}

When i run above code i am getting exception like :

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Enum
like image 758
rajesh Avatar asked Sep 01 '16 09:09

rajesh


People also ask

Does MySQL support ENUM?

In MySQL, an ENUM is a string object whose value is chosen from a list of permitted values defined at the time of column creation. The ENUM data type provides the following advantages: Compact data storage. MySQL ENUM uses numeric indexes (1, 2, 3, …) to represents string values.

How ENUM values are stored in MySQL?

As explained here, enums are stored as values between 0 (no valid value set) and 65,535 that are associated with an enumeration index. The value that is stored in the table is a 2 byte value, not a string.

How do I declare an ENUM in MySQL?

An ENUM is a string object whose value is decided from a set of permitted literals(Values) that are explicitly defined at the time of column creation. Succinct data storage required to store data in limited size columns.

Is hibernate criteria deprecated?

Since Hibernate 5.2, the Hibernate Criteria API is deprecated, and new development is focused on the JPA Criteria API. We'll explore how to use Hibernate and JPA to build Criteria Queries.


3 Answers

You can define another non-insertable and non-updatable field of String type mapped to the same column:

@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;
      }
}

You don't need getters and setters for it and you can use it only in queries in which you need to treat gender as plain text:

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

Note that I also use Restrictions.ilike method as you probably want the comparison to be case insensitive.

like image 184
Dragan Bozanovic Avatar answered Oct 12 '22 23:10

Dragan Bozanovic


define your enum outside in a saperate file so that you can access it from anywhere and then use it like this:

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

EDIT 1

As you specified, if the values are dynamic, then you can define a function like this in your enum.

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;
    }
}

and then you can use them like:

Criteria criteria = session.createCriteria(Contact.class)
   .add(Restrictions.like("gender", Gender.getGender("fema"), MatchMode.ANYWHERE)));
like image 29
Raman Sahasi Avatar answered Oct 13 '22 01:10

Raman Sahasi


Try this instead (assuming the intention is to only return male contacts):

Criteria criteria = session.createCriteria(Contact.class)
    .add(Restrictions.eq("gender", Contact.Gender.MALE));
like image 41
Steve Chambers Avatar answered Oct 13 '22 00:10

Steve Chambers