2016-09-01 63 views
5

這是代碼:獲取錯誤而在MySQL表枚舉列執行條件查詢冬眠

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 

回答

4

您可以定義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方法,因爲您可能希望比較不區分大小寫。

+0

我認爲這是一個可愛的黑客,但爲什麼不休眠處理它呢? – IntelliData

+0

@IntelliData枚舉時,在這方面做一個通用的行爲在邏輯上有點困難,因爲枚舉也可以通過使用'EnumType.ORDINAL'存儲爲數字,所以我假定作者只是選擇了一致所有案件的行爲。 –

+0

可惜有沒有辦法downvote休眠功能....;) – IntelliData

3

在saperate文件之外定義枚舉,讓您在f訪問ROM任意位置,然後使用它是這樣的:

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))); 
+0

沒有爲搜索參數的動態值。像馬,馬,fe,女 – rajesh

+0

@rajesh看到我編輯的答案。 –

+0

@rajesh你能接受這個頁面的答案嗎?謝謝! –

1

如果你想到你想要做什麼,在enum列上進行部分匹配,那麼hibernate並沒有什麼意義。

你已經告訴休眠,性別是一個枚舉,並且只有兩個允許的值 - 男性或女性。所以這些是hibernate期望/允許的唯一可能的值。它看起來像只能使用Enum類型的完全匹配上的限制類來查詢枚舉。

但是,您可以使用下面的查詢來完成此操作,而無需更改您的實體模型。所以如果你傳入「f」或「fem」,它只會給你女性,但大多數其他連擊都會返回所有女性的所有男性字母 - 你顯然可以改變它產生類似參數的方式,所以你可以匹配在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); 
} 

希望幫助

+0

即使有完全匹配的標準,它不起作用... – IntelliData

+0

@IntelliData不知道你有什麼問題,因爲我有它提供的代碼與一個附加數據庫並通過郵遞員解僱休息查詢。 –

2

試試這個(假設其意圖是隻返回男性接觸):

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