2010-05-26 83 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