2011-10-13 3 views
5

以前はJavaのenumクラスを定数値として使用したことはありませんでしたが、これまでは一般的にpublic finalメソッドを使用してきました。私は今enumを使い始めました。私はtoString()メソッドをオーバーライドして、enum名とは異なる値を返します。Javaのenum toString()をオーバーライドする

名前付きパラメータを持つTypedQueryを作成するJPAコードがあります。そのうちの1つは列挙型の値です。 Status.ACTIVEを使用してパラメータを設定するだけでは、適切な「A」値が得られますが、型は実際にはStringではなくStatusであるため、例外がスローされます。これは、明示的にtoString()メソッドを呼び出す場合にのみ機能します。私は単純にtoString()メソッドをオーバーライドすると、クラスの型が何であってもString型が返されると考えました。

これがenumです:

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)'で注釈されていますか?もしそうなら、クエリでenumをうまく使うことができるはずです。 –

答えて

3

MechanicTimeEvent Beanのフィールドstatusは列挙型ですか。 そうでない場合は、列挙型Statusに変更することをお勧めします。

あなたはまた、私はあなたの列挙型の値の一部を除去することをお勧め@Enumerated(EnumType.STRING)

でそれに注釈を付けることができ、 だけのような名前を使用します。ロフトが言うだけのよう

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

enum型ではありませんでしたので、ステータスを入力して、あなたが提案した注釈を追加しました。私はそのトリックをしたと思う。レコードが見つかった場合、OpenJPAはArgumentExceptionをスローし、なぜ私のクエリの構文をチェックするかを指示します。 –

+0

stringの代わりに列挙型の値を使用しましたか?つまり、query.setParameter( "status"、Status.ACTIVE) – lauwie

+0

実際には、データベースにはA、P、Fという値しか格納されていないため、 select文を作成すると、OpenJPAはクエリから返された値AをenumのvalueOfメソッドに渡します。列挙型でAが見つからないため、例外がスローされます。 valueOfメソッドはfinalなので、私はそれをオーバーライドできません。 –

0

このまたはあなたは、単に値のgetterを実装します:

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ある

public String getValue() 

そして、あなたはそれを呼び出しますあなたのコード内:

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

toStringは、PrintStream.println(System.out.printlnを覚えておいてください)のようないくつかのメソッドによって明示的に呼び出される、または+演算子を使用して連結中に考慮される単なる通常のメソッドです。すべてのメソッドがこの動作を実装する必要はありません。

私は私が正しくあなたの質問を理解していれば、あなたは他の方法で回避をマッピング列挙を行う必要があります代わりに、オーバーライドのtoString

3

をあなたはgetValueのようなより説明的なメソッド名を使用することをお勧めして明示的に呼び出すと思います。このようにして、状態は状態として保存され、JPAは名前A、P、Fに基づいて列挙を処理します。

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

このようにして、JPAに対してtoString()メソッドを呼び出さずにステータスを渡すことができます。 ENUMの.name()メソッドが自動的に呼び出され、永続性のステータスコードが取得されます。

+1

フィールド名を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()の実装では、特に将来、enum名が追加されることになります。インスタンス化時に文字列値を代入して代わりに返すことが最善です。 – initialZero

+0

...質問ソリューションが提供する...そのコードは読みやすく、 "文字列マッピング"(ACTIVE( "A") ')の間のローカリティは、タイプミスでコードを実行することを避けます(例:' case 2: name = "F" ')。また、スイッチのデフォルト値は無意味です。 –

関連する問題