2010-05-26 52 views
3

我有一个Java枚举:使用PreparedStatement以保持Java的枚举的数组Postgres的枚举数组

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

和相应的Postgres的枚举:

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

在我的数据库中,我有一个列有一列包含“设备”项目的列表:

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

最后当我ru在我的应用程序中,我有一组“设备”枚举,我想使用Prepared Statement将其保存到数据库中,而对于我的生活,我无法弄清楚如何去做。

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

只需回答下面的一些评论。这个例子只是说明性的,而不是我正在使用的确切代码。我知道日期可能是非法的列名称,并没有真正想到,当我设置示例:) 我会正常化,但想要如果工作与一个枚举数组是可能的。如果没有某种类型的黑客,它听起来不像它。 – McGin 2010-05-27 07:09:29

回答

3

您应该阅读this

我建议你的代码看起来更象这样:

// 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()',而不是'getName()'。在检索时,对ResultSet#getString()'的结果使用'Enum#valueOf(String)'。 +1进行标准化。 – BalusC 2010-05-26 22:52:20

+0

我已经阅读过那篇文章duffymo,完美的单枚枚举条目,但不适用于数组。正如你所建议的我应该正常化,但只是想知道如果阵列是可能的。 – McGin 2010-05-27 07:11:31

3

我遇到了这个确切的问题,并不能找到一个很好的解决方案。

我最终解决上的解决办法是插入作为String数组:

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

,并有在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; 

我不满意这点解决方案,但它确实有效,并且不需要任何特定的JDBC wizardry。

+0

请注意,如果您愿意为每个声明执行操作,您也可能只需在准备好的声明中使用演员表。 – 2010-05-26 22:41:59

1

您试图在纯JDBC中执行两个非标准的事情:枚举和数组。它们都不是非常简单 - 尽管两者都可以完成。但我建议不要这样做:我更喜欢使用ad-hoc-enums(只是某些参数表中的整数),并且避免数据库内的数组,除非是非常特殊的情况。如果你坚持,一次攻击一个问题。

顺便说一句,您还有两个其他问题:具有混合大小写的标识符(表和列名)(必须引用以避免postgresql折叠为小写)以及具有保留sql字(日期)作为名称的列。这并不坏,但它肯定不会让你的开发人员生活更轻松... 更多BTW:当心\"equipment \"

+0

第一次使用Postgres,感谢关于案例的信息。想知道为什么我需要引号 – McGin 2010-05-27 07:05:57

+0

@McGin:一些更多信息在这里http:// stackoverflow。COM /问题/ 2774406/psycopg2-犯规样表名,也就是说,启动与-A-小写字母/ 2776308#2776308 – leonbloy 2010-05-27 11:36:23