148 votes

Des moyens pour enregistrer les énumérations dans la base de données

Je me demande quelles sont les meilleures façons d'économiser de l'enums dans une base de données.

Je sais qu'il y a name() et valueOf() méthodes pour en faire une Corde. Mais existe-il des autres (souple) pour le stockage de ces valeurs?

Est-il une façon intelligente de faire des numéros uniques (ordinal() n'est pas sûr à utiliser)?

Les commentaires et les suggestions seraient utiles :)

Mise à jour:

Merci pour toutes géniales et de réponses rapides! C'était comme je m'en doutais.

Toutefois, une note de "boîte à outils"; C'est une des manières. Le problème est que j'aurais à ajouter les mêmes méthodes avec chaque type enum j'ai créer. C'est beaucoup de code dupliqué et, à l'heure actuelle, Java ne supporte pas toutes les solutions à cette (Vous ne pouvez pas laisser enum étendre à d'autres classes).

Cependant, merci pour toutes les réponses!

196voto

Ian Boyd Points 50743

Nous ne jamais stocker les énumérations numérique des valeurs ordinales plus; il rend le débogage et de soutien est beaucoup trop difficile. Nous stockons la réelle valeur de l'énumération converti en chaîne:

public enum Suit { Spade, Heart, Diamond, Club }

Suit theSuit = Suit.Heart;

szQuery = "INSERT INTO Customers (Name, Suit) " +
          "VALUES ('Ian Boyd', %s)".format(theSuit.name());

et puis lisez avec:

Suit theSuit = Suit.valueOf(reader["Suit"]);

Le problème était dans le passé à regarder Enterprise Manager et essayer de les déchiffrer:

Name                Suit
==================  ==========
Shelby Jackson      2
Ian Boyd            1

les versets

Name                Suit
==================  ==========
Shelby Jackson      Diamond
Ian Boyd            Heart

le dernier est beaucoup plus facile. L'ancien nécessaires pour arriver au code source et de trouver les valeurs numériques qui ont été attribués aux membres de l'énumération.

Oui il faut plus d'espace, mais l'énumération des noms de membres sont courts, et les disques durs ne sont pas chers, et c'est beaucoup plus la peine de vous aider lorsque vous rencontrez un problème.

En outre, si vous utilisez des valeurs numériques, vous êtes lié pour eux. Vous ne pouvez pas bien d'insérer ou de réorganiser les membres sans avoir à forcer la vieille valeurs numériques. Par exemple, la modification de la fonction de l'énumération:

public enum Suit { Unknown, Heart, Club, Diamond, Spade }

aurait pour devenir :

public enum Suit { 
      Unknown = 4,
      Heart = 1,
      Club = 3,
      Diamond = 2,
      Spade = 0 }

afin de maintenir l'héritage des valeurs numériques stockées dans la base de données.

48voto

Tom Points 6758

Sauf si vous avez des raisons de performance pour l'éviter, je vous conseille d'utiliser un tableau distinct pour l'énumération. Utilisation de clé étrangère à l'intégrité, à moins que l'extra de recherche vraiment vous tue.

Convient à table:

suit_id suit_name
1       Clubs
2       Hearts
3       Spades
4       Diamonds

Les joueurs de la table

player_name suit_id
Ian Boyd           4
Shelby Lake        2
  1. Si jamais vous refactoriser votre énumération des classes avec un comportement (comme la priorité), votre base de données déjà des modèles correctement
  2. Votre DBA est heureux parce que votre schéma est normalisé (le stockage d'un nombre entier par joueur, au lieu de toute une chaîne de caractères, qui peut ou peut ne pas avoir de fautes de frappe).
  3. Vos valeurs de base de données (suit_id) sont indépendants de votre valeur de l'énumération, qui vous permet de travailler sur des données provenant d'autres langues.

7voto

oxbow_lakes Points 70013

Je dirais que le seul mécanisme ici est d'utiliser la Chaîne de caractères name() de la valeur. Lors de l'écriture dans la base de données, vous pourriez utiliser une procédure stockée pour insérer la valeur et lors de la lecture, de l'utilisation d'un point de Vue. De cette manière, si les enums changement, il y a un niveau d'indirection dans la procédure stockée/vue d'être en mesure de présenter les données de la valeur d'enum sans "imposer" cela sur la DB.

7voto

toolkit Points 27248

Comme vous le dites, ordinal est un peu risqué. Considérons par exemple:

public enum Boolean {
    TRUE, FALSE
}

public class BooleanTest {
    @Test
    public void testEnum() {
        assertEquals(0, Boolean.TRUE.ordinal());
        assertEquals(1, Boolean.FALSE.ordinal());
    }
}

Si vous avez stocké ce que les ordinaux, vous pourriez avoir des lignes comme:

> SELECT STATEMENT, TRUTH FROM CALL_MY_BLUFF

"Alice is a boy"      1
"Graham is a boy"     0

Mais qu'advient-il si vous avez mis à jour Boolean?

public enum Boolean {
    TRUE, FILE_NOT_FOUND, FALSE
}

Cela signifie que tous vos mensonges deviennent interprété à tort comme "fichier non trouvé"

Mieux d'utiliser une représentation de chaîne

5voto

JeeBee Points 11882

Nous venons de stocker les enum nom lui-même - c'est plus lisible.

Nous n'avons déconner avec le stockage des valeurs spécifiques pour les énumérations où il y a un ensemble limité de valeurs, par exemple, cette enum qui dispose d'un nombre limité de statuts que nous utilisons un char à représenter (plus de sens qu'une valeur numérique):

public enum EmailStatus {
    EMAIL_NEW('N'), EMAIL_SENT('S'), EMAIL_FAILED('F'), EMAIL_SKIPPED('K'), UNDEFINED('-');

    private char dbChar = '-';

    EmailStatus(char statusChar) {
        this.dbChar = statusChar;
    }

    public char statusChar() {
        return dbChar;
    }

    public static EmailStatus getFromStatusChar(char statusChar) {
        switch (statusChar) {
        case 'N':
            return EMAIL_NEW;
        case 'S':
            return EMAIL_SENT;
        case 'F':
            return EMAIL_FAILED;
        case 'K':
            return EMAIL_SKIPPED;
        default:
            return UNDEFINED;
        }
    }
}

et quand vous avez beaucoup de valeurs que vous avez besoin d'avoir une Carte à l'intérieur de votre enum pour garder que getFromXYZ méthode des petits.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X