2010-05-26 4 views
3

Je Java Enum:L'utilisation d'un PreparedStatement pour persister un tableau de Java énumérations à un tableau de Postgres énumérations

public enum Equipment { Hood, Blinkers, ToungTie, CheekPieces, Visor, EyeShield, None;} 

et Postgres correspondant ENUM:

CREATE TYPE equipment AS ENUM ('Hood', 'Blinkers', 'ToungTie', 'CheekPieces', 'Visor', 'EyeShield', 'None'); 

Dans ma base de données que j'ai une table qui a une colonne contenant un tableau d'articles "équipement":

CREATE TABLE "Entry" (
    id bigint NOT NULL DEFAULT nextval('seq'::regclass), 
    "date" character(10) NOT NULL, 
    equipment equipment[] 
); 

Et enfin quand je suis ru Dans mon application, j'ai un tableau des enums "Equipment" que je veux persister dans la base de données en utilisant une déclaration préparée, et pour la vie de moi je ne peux pas comprendre comment le faire.

StringBuffer sb = new StringBuffer("insert into \"Entry\" "); 
sb.append("(\"date\", \"equipment \")"); 
sb.append(" values (?, ?)"); 
PreparedStatement ps = db.prepareStatement(sb.toString()); 

ps.setString("2010-10-10"); 
ps.set??????????? 
+0

Juste pour répondre à certains des commentaires ci-dessous. L'exemple est seulement illustratif, pas le code exact que j'utilise. Je sais que la date est probablement illégale en tant que nom de colonne, n'a pas vraiment pensé pendant que je mettais en place l'exemple :) Je vais normaliser, mais je voulais si travailler avec un tableau enum était possible. Ne sonne pas comme ci-dessous sans un hack quelconque – McGin

Répondre

3

Vous devriez lire this.

Je suggère que votre code ressemble plus à ceci:

// A column named "date" is probably illegal and not very illustrative. "date" is a keyword for most databases. 
    // Building a string that never changes again and again is a waste of CPU and heap 
    private static final String INSERT_SQL = "insert into Entry(date,equipment) values(?,?)"; 

    PreparedStatement ps = db.prepareStatement(INSERT_SQL); 

    // Use the type system properly. Dates should be DATE type columns in a database. Why string?  
    ps.setDate(entryDate); 

    // You shouldn't want to insert an array of values; that's not normalized. 
    ps.setString(equipmentEnumValue.name()); 
+0

Psst, 'name()', pas 'getName()'. Et lors de la récupération, utilisez 'Enum # valueOf (String)' sur le résultat de 'ResultSet # getString()'. +1 pour la normalisation. – BalusC

+0

J'avais déjà lu cet article duffymo, fonctionne parfaitement pour les entrées enum simples, mais pas pour les tableaux. Comme vous le suggérez, je devrais normaliser, mais j'étais juste intéressé de savoir si les tableaux étaient possibles. – McGin

3

je suis tombé sur ce problème précis, et n'a pas pu trouver une bonne solution.

La solution que je fini par installer sur était d'insérer comme un tableau de chaîne:

conn.createArrayOf("varchar", elements.toArray()); 

et d'avoir une distribution d'affectation dans le DB:

CREATE OR REPLACE FUNCTION cast_meal_array(src_str character varying[]) RETURNS meal_type[] AS $$ 
BEGIN 
RETURN src_str::text[]::meal_type[]; 
END; 
$$ LANGUAGE plpgsql; 

DROP CAST IF EXISTS (character varying[] as meal_type[]); 
CREATE CAST (character varying[] AS meal_type[]) WITH FUNCTION cast_meal_array(character varying[]) AS assignment; 

Je n'étais pas content de ce solution, mais cela fonctionne et ne nécessite aucune compétence particulière de JDBC.

+0

Notez que vous pourriez aussi probablement avoir le cast sur votre instruction préparée, si vous êtes prêt à le faire pour chaque déclaration. –

1

Vous tentez d'effectuer deux opérations non standard dans JDBC simple: enums et arrays. Aucun d'eux n'est très simple - bien que les deux peuvent être faits. Mais je déconseille les deux: je préfère utiliser ad-hoc-enums (juste des entiers dans une table paramétrique), et éviter les tableaux dans la base de données, sauf dans des cas très spéciaux. Si vous insistez, attaquez un problème à la fois.

BTW, vous avez deux autres problèmes: identifiants (tables et noms de colonnes) avec des cas mixtes (qui doivent être cités pour éviter le repliement postgresql en minuscules), et une colonne avec un mot sql réservé (date) comme nom. Ce n'est pas mauvais, mais cela ne rendra certainement pas la vie de votre développeur plus facile ... Et plus BTW: méfiez-vous de cet espace après \"equipment \"

+0

Première fois en utilisant Postgres, merci pour l'info sur l'affaire. Se demandait pourquoi j'avais besoin des citations – McGin

+0

@McGin: un peu plus d'informations ici http: // stackoverflow.com/questions/2774406/psycopg2-doesnt-comme-table-noms-que-commencer-avec-une-lettre-minuscule/2776308 # 2776308 – leonbloy