2011-10-13 104 views
5

我從來沒有真正使用Java枚舉類之前的常量值,我通常在過去使用「公共最終」的方法。我已經開始使用枚舉了,並且我重寫了toString()方法返回與枚舉名稱不同的值。Java枚舉重寫toString()

我有一些JPA代碼,我在其中創建一個具有命名參數的TypedQuery,其中一個是枚舉值的字符串表示形式。如果我只是使用Status.ACTIVE設置參數,我會得到正確的「A」值,但會拋出一個異常,因爲它的類型實際上是Status而不是String。它只有在我顯式調用toString()方法時纔有效。我認爲只要重寫toString()方法就會返回一個String類型,不管類的類型是什麼。

這是枚舉:

public enum Status { 
    ACTIVE ("A"), 
    PENDING ("P"), 
    FINISHED ("F"); 

    private final String value; 

    Status(String value) { 
     this.value = value; 
    } 

    public String toString() { 
     return value; 
    } 
}; 

這是TypedQuery:

TypedQuery<MechanicTimeEvent> query = entityManager().createQuery("SELECT o FROM MechanicTimeEvent o WHERE o.id.mechanicNumber = :mechanicNumber AND o.id.status = :status", MechanicTimeEvent.class); 
    query.setParameter("mechanicNumber", mechanicNumber); 
    query.setParameter("status", Status.ACTIVE.toString()); 
+0

可以添加該字段到問題的映射嗎? – Augusto

+1

如果你正在尋找一個更簡潔的方式來寫它,'query.setParameter(「status」,Status.ACTIVE +「」);'將工作。 – Eric

+1

是你的'@ Entity'類型爲'Status'的字段,是否用'@Enumerated(EnumType.STRING)'註解?如果是這樣,你應該能夠在查詢中使用枚舉就好了。 –

回答

3

MechanicTimeEvent bean的字段status是枚舉類型嗎? 如果不是,我建議將其更改爲枚舉類型Status

你可以用@Enumerated(EnumType.STRING)

其標註此外,我會建議刪除您的枚舉值部分和 只是使用的名字,如:

public enum Status { 
    ACTIVE, 
    PENDING, 
    FINISHED; 
} 
+0

這不是枚舉類型,所以我將其更改爲鍵入Status並添加了您建議的註釋。我認爲這是訣竅。奇怪的是,如果我的查詢沒有找到記錄,那麼它工作正常,但是如果它發現一條記錄,那麼OpenJPA會拋出一個ArgumentException並告訴我檢查我的查詢語法,不知道爲什麼。 –

+0

您是否使用枚舉值而不是字符串?:ie query.setParameter(「status」,Status.ACTIVE) – lauwie

+0

實際上,問題是由於數據庫只存儲值,即:A,P或F,創建一個select語句,OpenJPA將查詢返回的值A傳遞給enum的valueOf方法。由於它在枚舉中沒有找到A,所以會拋出異常。 valueOf方法是final的,所以我不能覆蓋它。 –

0

,或者你只是實現該值的吸氣劑:

public String getValue() 

你叫它在您的代碼中:

query.setParameter("status", Status.ACTIVE.getValue()); 
0

toString只是Object中的一個普通方法,它被PrintStream.println(記住System.out.println)等方法顯式調用,或者在使用+運算符連接時考慮。並非每個方法都需要實現這種行爲。

我建議你使用一個更具描述性的方法名稱,比如getValue並調用它明確代替覆蓋toString

3

的如果我正確理解你的問題,你應該做的枚舉映射周圍的其他方式。通過這種方式,狀態被存儲爲狀態,並且JPA將基於其名稱A,P,F來處理枚舉。

public enum Status { 
    A("ACTIVE"), 
    P("PENDING"), 
    F("FINISHED"); 

通過這種方式,您可以在不調用toString()方法的情況下將狀態傳遞給JPA。 ENUM上的.name()方法將被自動調用以獲取持久性的狀態碼。

+1

你不應該將字段名減少爲一個字母,因爲這是數據庫/任何用途的形式。你不能只重寫'.name()'? – Eric

+2

Enum.name()方法是final的,所以不能被覆蓋。 –

+2

這樣做的目的就是如果別人讀取代碼,Status.ACTIVE比Status.A更明顯。 –

-1
java.lang.Enum said clearly: 
/** 
* Returns the name of this enum constant, exactly as declared in its 
* enum declaration. 
* 
* <b>Most programmers should use the {@link #toString} method in 
* preference to this one, as the toString method may return 
* a more user-friendly name.</b> This method is designed primarily for 
* use in specialized situations where correctness depends on getting the 
* exact name, which will not vary from release to release. 
* 
* @return the name of this enum constant 
*/ 
public final String name() 

就像閣樓說,您可以使用「名稱」方法來獲取名稱。 也可以使用toString()方法。

當然它只是這個枚舉常量的名字。

5
public enum Status { 
    ACTIVE, 
    PENDING, 
    FINISHED; 

    @Override 
    public String toString() { 
     String name = ""; 
     switch (ordinal()) { 
     case 0: 
      name = "A"; 
      break; 
     case 1: 
      name = "P"; 
      break; 
     case 2: 
      name = "F"; 
      break; 
     default: 
      name = ""; 
      break; 
     } 
     return name; 
    } 
}; 
+6

這個toString()實現需要太多的維護,尤其是如果枚舉名將在未來添加到。最好在instanciation上分配一個字符串值,然後返回。 – initialZero

+0

...問題解決方案提供。該代碼更具可讀性,並且「字符串映射」('ACTIVE(「A」)')之間的局部性也避免了運行帶有拼寫錯誤的代碼(即:case 3:name =「E」'而不是'case 2: name =「F」')。另外,開關默認值沒有意義。 –