Il est possible de définir des énumérations dans JPA en utilisant soit
@Enumerated(EnumType.ORDINAL)
ou
@Enumerated(EnumType.STRING)
Je me demande quels sont les avantages et les inconvénients de ces deux définitions?
J'ai entendu dire que ORDINAL fonctionne mieux (est plus rapide) que STRING avec EclipseLink.
Est-ce vrai?
Je vais toujours STRING
.
La rapidité est rarement le problème le plus important - la lisibilité et la maintenabilité sont plus importantes.
J'utilise STRING
car il est beaucoup plus facile d'inspecter manuellement les lignes de la base de données, mais plus important encore, je peux faire deux choses, sans toucher à la base de données, la ORDINAL
ne peut pas gérer:
Ces deux modifications vont modifier les valeurs ordinales des énumérations déjà utilisées dans la base de données, cassant ainsi les données existantes si vous utilisez ORDINAL
.
Si vous modifiez une valeur enum (pas si commune), sa gestion est simple:
UPDATE table SET enum_column = 'NEW_ENUM_NAME' where enum_column = 'OLD_ENUM_NAME';
Il est probable que ORDINAL
soit plus efficace, mais c'est mineur. Il y a quelques inconvénients à ORDINAL
:
Avec STRING
, vous ne pouvez pas renommer vos énumérations.
Choisissez-en un et utilisez-le tout au long de l'application - soyez cohérent.
Si votre base de données doit être utilisée par d'autres clients/langues - utilisez STRING
, elle sera plus lisible.
C'est une bonne question. Dans le passé, j'ai utilisé String mais aujourd'hui, ma préférence va habituellement à Ordinal.
Le principal inconvénient de la chaîne concerne les administrateurs de base de données. Avec la chaîne ils n'ont aucune idée des valeurs possibles de la colonne, car ces informations se trouvent dans le code de l'application. Seul l'administrateur de base de données peut avoir une idée des valeurs possibles regroupant les informations existantes sur la table, mais il ne sera jamais sûr des autres valeurs possibles ni de l'ajout de nouvelles valeurs jusqu'à ce que l'application les insère dans la table.
À l'Ordinal, vous avez le même problème. Mais ma préférence pour Ordinal est venue à une solution au problème de DBA qui semble naturelle à la base de données. Vous créez une nouvelle table pour afficher les valeurs possibles de l'énumérateur sur la base de données, avec une clé étrangère entre la colonne (valeur ordinale) et cette nouvelle table. Cette stratégie est décrite et mise en œuvre ici .
En ce qui concerne le problème selon lequel quelqu'un pourrait réorganiser l'énumérateur et casser le système, un simple test unitaire peut résoudre ce problème et garantir que personne ne les réordonnera sans un bon avertissement. La même idée vaut pour renommer l'énumérateur. Ainsi, renommer (sur String) ou réorganiser (sur Ordinal) accidentellement n’est pas vraiment un argument de poids contre l’approche String ou Ordinal.
En passant, les développeurs ont plus besoin de renommer que de réorganiser un énumérateur, c’est donc un point positif supplémentaire dans l’utilisation de Ordinal.
Ainsi, avec cette approche, vous résolvez le problème principal de l'Ordinal (maintenant lisible), les informations occuperont moins d'espace sur la base de données et votre administrateur de base de données sera content.
Je préfère l’utilisation de Ordinal
mais ceci dépend vraiment de l’utilisation.
Par exemple:
Vous avez un enum, pour sauvegarder tous vos états d'utilisateur, dans ce cas, l'ordre n'a pas d'importance, et vous pouvez ajouter d'autres états à l'avenir (la meilleure utilisation est @Enumerated(EnumType.ORDINAL)
):
public enum UserStates { ACTIVE, DELETED, PENDING }
Mais maintenant, vous avez un enum, pour sauver les Plantes dans le système solaire (Meilleure utilisation @Enumerated(EnumType.STRING)
):
public enum Planets {MERCURY,VENUS,EARTH,MARS,JUPITER,SATURN,URANUS,Neptune,PLUTO,NINE}
Maintenant, pensez que vous voulez réorganiser vos planètes, avec @Enumerated(EnumType.ORDINAL)
, vous ne pouvez pas, car votre base de données ne peut pas connaître le nouvel ordre dans votre fichier Java.
Vous pouvez réorganiser vos Plantes en utilisant @Enumerated(EnumType.STRING)
car votre planète est liée au nom de l’énum, pas à son ordre.
Quoi qu'il en soit, vous pouvez modifier vos noms @Enumerated(EnumType.STRING)
enum car ils sont liés à la commande, mais vous ne pouvez pas modifier vos noms @Enumerated(EnumType.STRING)
enums car ils utiliseront de nouvelles énumérations.
Les types de chaîne sont plus lisibles dans la base de données, mais occuperont plus de taille qu'une donnée ordinale. Peut-être utile si la base de données est utilisée par plus de clients, mais il vaut mieux avoir une bonne documentation du logiciel que de gagner 1000 fois "EARTH" plutôt que "4"
USERSTATE
------------
ID | STATE |
------------
1 | 1
2 | 2
3 | 1
Planets
------------
ID | Name |
------------
1 | EARTH
2 | EARTH
3 | MARS
4 | EARTH
Cela dépend de votre application. S'il y a plus de chances que vous ajoutiez plus d'énums, utilisez le type String, s'il y a plus de chances que vous changiez le nom de vos enums, utilisez Ordinal.