web-dev-qa-db-ja.com

JPA Enum ORDINAL対STRING

いずれかを使用してJPAで列挙を定義することが可能です

@Enumerated(EnumType.ORDINAL)

または

@Enumerated(EnumType.STRING)

これら2つの定義の利点と欠点は何でしょうか。

EclipseLinkを使用すると、ORDINALはSTRINGよりもパフォーマンスが良い(高速である)と聞きました。
本当?

41
jst99

いつもSTRINGに行きます。

速度がめったに最も重要な問題となることはありません。読みやすさと保守性が重要ですmore重要です。

STRINGを使用するのは、データベースから行を手動で検査する方がはるかに簡単だからです。しかし、より重要なのは、データベースに触れずにORDINALが処理できない2つのことです。

  1. 列挙型のorderを変更できます
  2. 私は挿入列挙リストの真ん中に新しい列挙をすることができます

これらの変更はどちらも、データベースですでに使用されている列挙型の序数値を変更するため、ORDINALを使用している場合は既存のデータが壊れます。

Enum値を変更する場合(それほど一般的ではありません)、その処理は簡単です。

UPDATE table SET enum_column = 'NEW_ENUM_NAME' where enum_column = 'OLD_ENUM_NAME';
67
Bohemian

ORDINALの方が効率的ですが、それはマイナーです。 ORDINALにはいくつかの欠点があります。

  • データベースでは読みにくい
  • enum定義を並べ替えると、データベースの一貫性が失われます。

STRINGでは、列挙型の名前を変更することはできません。

それらの1つを選択し、アプリケーション全体で使用します-一貫性があります。

データベースが他のクライアント/言語で使用される場合-STRINGを使用すると、より読みやすくなります。

17
Bozho

私はOrdinalの使用を好みますが、これは実際には使用方法によって異なりますです。

例として:

すべてのユーザー状態を保存するための列挙型があり、この場合、順序は重要ではありません。将来、さらに状態を追加できます(最適な用途は@Enumerated(EnumType.ORDINAL))です。

_public enum UserStates { ACTIVE, DELETED, PENDING }
_

しかし、今では、Planesを太陽系に保存するための列挙型があります(最善の使用法@Enumerated(EnumType.STRING)):

_public enum Planets {MERCURY,VENUS,EARTH,MARS,JUPITER,SATURN,URANUS,Neptune,PLUTO,NINE}
_

データベースが_ Javaファイル内の新しい順序を認識できないため、@Enumerated(EnumType.ORDINAL)では不可能です。

Planetは列挙型の順序ではなく列挙名にリンクされているため、@Enumerated(EnumType.STRING)を使用してPlantesを並べ替えることができます。

とにかく、注文にリンクされているので@Enumerated(EnumType.STRING) enumを変更できますが、@Enumerated(EnumType.STRING) enumは新しいenumのように使用されるため変更できません。

文字列型はデータベースで読みやすくなりますが、通常のデータよりも多くのサイズを占有します。データベースがより多くのクライアントで使用されている場合はおそらく便利ですが、「EARTH」を「4」よりも1000倍節約するよりも、ソフトウェアの優れたドキュメントを用意する方が良いでしょう。

_USERSTATE
------------
ID | STATE |
------------
1 | 1
2 | 2
3 | 1

Planets
------------
ID | Name |
------------
1 | EARTH
2 | EARTH
3 | MARS
4 | EARTH
_
5
Genaut

これは良い質問です。以前はStringを使用していましたが、現在は通常Ordinalが好みです。

文字列の主な欠点はDBAです。文字列を使用すると、それらの情報には何も表示されません。この情報はアプリケーションコードに含まれているため、列の可能な値は何ですか。 DBAは、テーブル上の既存の情報をグループ化する考えられる値についてある程度の知識を持つことができますが、アプリケーションがそれらをテーブルに挿入するまで、他の考えられる値や新しい値が追加されるかどうかはわかりません。

序数では同じ問題があります。しかし、Ordinalの私の好みは、データベースに自然に見えるDBA問題の解決策になりました。列(通常の列挙値)とこの新しいテーブルの間に外部キーを使用して、データベース上の列挙子の可能な値を示す新しいテーブルを作成します。この戦略は説明され、実装されています here

誰かが列挙子を並べ替えてシステムを壊す可能性がある問題については、単純な単体テストでこの問題を処理し、適切な警告なしに誰も並べ替えないことを保証できます。同じ考え方は、列挙子の名前を変更する場合にも当てはまります。したがって、誤って名前を変更する(Stringで)または並べ替え(Ordinalで)は、実際にはStringまたはOrdinalのアプローチに対する強力な主張ではありません。

ちなみに、開発者はEnumeratorを並べ替えるよりも名前を変更する必要があるため、これはOrdinalを使用する上でのもう1つの利点です。

したがって、このアプローチでは、序数の主な問題(現在は読み取り可能)を解決し、情報がデータベースの占有スペースを減らし、DBAが満足するようになります。

2
Dherik

これはアプリケーションに依存します。enumを追加する可能性が高い場合はString型を使用し、enumの名前を変更する可能性が高い場合はOrdinalを使用します。

0
samid hamza

EnumType.STRINGを使用します。 EnumType.ORDINALの欠点は、時間の影響と、列挙型を論理的な順序で保持したいということです。 EnumType.ORDINALを使用すると、新しい列挙型要素をリストの最後に追加する必要があります。そうしないと、すべてのレコードの意味が誤って変更されてしまいます。このリンクを確認してください: https://tomee.Apache.org/examples-trunk/jpa-enumerated/

0
Mendon Ashwini

ここには良いアドバイスがたくさんありますが、まだ見ていなかったものを追加したいだけです。

選択するソリューションに関係なく、使用する必要があることを示す大きな脂肪の警告を列挙型クラスの上部に追加することを忘れないでください。うまくいけば、他の開発者があなたがこれを行ったのを見て、列挙を保存するために同じ方法を使用するでしょう。

0
Steven B