Question

J'ai une table qui mappe String-> Entier.

Au lieu de créer un ENUM statiquement, je veux remplir le ENUM avec des valeurs d'une base de données. Est-ce possible?

Alors, plutôt que delcaring cette statiquement:

public enum Size { SMALL(0), MEDIUM(1), LARGE(2), SUPERSIZE(3) };

Je veux créer cette dynamique ENUM puisque les nombres {0,1,2,3} sont essentiellement aléatoire (parce qu'ils sont générées automatiquement par la colonne AUTOINCREMENT de la base de données).

Était-ce utile?

La solution

Non. Énumérations sont toujours fixés à la compilation. La seule façon que vous pourriez faire serait de générer dyamically le bytecode concerné.

Cela dit, vous devriez probablement travailler sur les aspects d'un ENUM vous êtes réellement intéressé. Je présume que vous ne le voulez pas utiliser une déclaration sur eux switch, car cela signifierait un code statique et vous n » sais les valeurs statiquement ... de même, toute autre référence dans le code.

Si vous voulez vraiment juste une carte de à String Integer, vous pouvez simplement utiliser un que vous remplissez Map<String, Integer> au moment de l'exécution, et vous avez terminé. Si vous voulez que les caractéristiques EnumSet, ils seraient un peu plus délicat à reproduire avec la même efficacité, mais il peut être possible avec un certain effort.

Alors, avant d'aller plus loin en termes de réflexion sur la mise en œuvre, je vous suggère de travailler ce que vos besoins réels sont.

(EDIT:. J'ai suppose que cette ENUM est entièrement dynamique, à savoir que vous ne connaissez pas le nom ou même le nombre de valeurs, il y a Si l'ensemble des noms est fixe et vous uniquement besoin de récupérer l'ID de la base de données, qui est une question très différente - voir réponse Andreas .)

Autres conseils

Ceci est un peu délicat, puisque la population de ces valeurs se produit au moment de la classe charge. Ainsi, vous aurez besoin d'un accès statique à une connexion de base de données.

Autant que j'apprécie ses réponses, je pense que Jon Skeet peut se tromper cette fois-ci.

Jetez un oeil à ceci:

public enum DbEnum {
    FIRST(getFromDb("FIRST")), SECOND(getFromDb("second"));

    private static int getFromDb(String s) {
        PreparedStatement statement = null;
        ResultSet rs = null;
        try {
            Connection c = ConnectionFactory.getInstance().getConnection();
            statement = c.prepareStatement("select id from Test where name=?");
            statement.setString(1, s);
            rs = statement.executeQuery();
            return rs.getInt(1);

        }
        catch (SQLException e) {
           throw new RuntimeException("error loading enum value for "+s,e);
        }
        finally {
            try {
                rs.close();
                statement.close();
            } catch (SQLException e) {
                //ignore
            }
        }
        throw new IllegalStateException("have no database");
    }

    final int value;

    DbEnum(int value) {
        this.value = value;
    }
}

Amélioration sur ce que Andreas a fait , vous peut charger le contenu de la base de données dans une carte afin de réduire le nombre de connexions de base de données nécessaires.

public enum DbEnum {
    FIRST(getFromDb("FIRST")),
    SECOND(getFromDb("second"));

    private Map<String,Integer> map;
    private static int getFromDB(String s)
    {
        if (map == null)
        {
           map = new HashMap<String,Integer>();
           // Continue with database code but get everything and
           // then populate the map with key-value pairs.
           return map.get(s);
        }
        else {
            return map.get(s); }
    }
}

énumérations ne sont pas dynamiques, de sorte que la réponse courte est que vous ne pouvez pas le faire.

Aussi jeter un oeil à la question Stack Overflow ENUM dynamique en C # .

Vous devez répliquer dans le code ce qui est dans la base de données (ou vice-versa). Voir cette question pour quelques bons conseils.

Dans toutes les langues que je connais énumérations sont statiques. Le compilateur peut faire quelques optimisations sur eux. Par conséquent, la réponse courte est non, vous ne pouvez pas.

La question est pourquoi vous voulez utiliser un ENUM de cette façon. Qu'attendez-vous? Ou autrement dit pourquoi ne pas utiliser une collection à la place?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top