2016-09-01 19 views
5

ten kod:Uzyskiwanie błąd podczas kryteria wykonywanie zapytań na kolumnę enum w tabeli mysql hibernacji

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

Gdzie płci jest enum kolumny typu w 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; 
     } 

} 

Kiedy uruchomić powyższy kod Otrzymuję wyjątek typu:

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

Odpowiedz

4

Można zdefiniować inny niż insercji i nie mogą być aktualizowane pole String typu odwzorowanym na tej samej kolumnie:

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

Nie potrzebujesz do tego programów pobierających i ustawiających i możesz go używać tylko w zapytaniach, w których musisz traktować gender jako zwykły tekst:

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

Należy pamiętać, że używam również metody Restrictions.ilike, ponieważ prawdopodobnie nie ma potrzeby rozróżniania wielkości liter w porównaniu.

+0

Myślę, że to sympatyczny hack, ale dlaczego hibernacja go nie obsługuje? – IntelliData

+0

@IntelliData Byłoby trochę logicznie trudne, aby generyczne zachowanie w tym zakresie, jeśli chodzi o wyliczenia, ponieważ wyliczenia mogą być również przechowywane jako liczby przy użyciu 'EnumType.ORDINAL', więc zakładam, że autorzy właśnie wybrał spójny zachowanie dla wszystkich przypadków. –

+0

Szkoda, że ​​nie ma sposobu na przywrócenie funkcji hibernacji ....;) – IntelliData

3

zdefiniuj swoje wyliczenie na zewnątrz w pliku saperatu, aby uzyskać do niego dostęp rom wszędzie, a następnie używać go tak:

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

EDIT 1

Jak podano, jeśli wartości są dynamiczne, to można zdefiniować funkcję takiego w swojej wyliczenia.

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

a następnie można wykorzystać je jak:

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

Jest dynamiczny wartość parametru wyszukiwania. jak ma, mal, fe, fema – rajesh

+0

@rajesh zobacz moją zredagowaną odpowiedź. –

+0

@rajesh, czy możesz zaakceptować odpowiedź z tej strony, która była dla ciebie odpowiednia? Dzięki! –

1

Jeśli myślisz o tym, co próbujesz zrobić, częściowe dopasowanie w kolumnie wyliczeniowej, to naprawdę nie ma sensu hibernacja.

Poinformowałeś hibernację, że płeć jest wyliczeniem i ma tylko dwie dopuszczalne wartości - MĘSKI lub KOBIETA. Są to więc jedyne możliwe wartości, których oczekuje/umożliwia program hibernacji. Wygląda na to, że możesz zapytać tylko w wyliczeniu przy użyciu klasy Ograniczenia w dokładnym dopasowaniu typu wyliczeniowego.

Ale możesz to zrobić, korzystając z poniższego zapytania bez zmiany modelu encji. Jeśli więc wpiszesz "f" lub "fem", to dostaniesz tylko kobietę, ale większość innych kombinacji zwróci wszystko jako wszystkie litery mężczyzny również u kobiet - możesz oczywiście zmienić sposób, w jaki generuje podobny parametr, abyś mógł dopasować na m%, ma%, mal%, aby znaleźć MALE, lub f%, fe% itd., aby znaleźć 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); 
} 

nadzieję, że pomoże

+0

Nie działa nawet z kryteriami ścisłego dopasowania ... – IntelliData

+0

@IntelliData nie jest pewien, jaki masz problem, ponieważ pracowałem z dostarczonym kodem dołączona baza danych i odpalanie zapytań dotyczących wypoczynku za pośrednictwem listonosza. –

2

Spróbuj zamiast (zakładając, że ma zamiar powrócić kontakty tylko samce):

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