2015-09-29 45 views
2

我創建了一個表,一個CITEXT柱,CITEXT(不區分大小寫版本的TEXT)是使用CREATE EXTENSION citext;PostgreSQL/JDBC - 如何使用參數CITEXT(TEXT)準備調用函數?

CREATE TABLE artists (
    artist_id SERIAL PRIMARY KEY, 
    artist  CITEXT UNIQUE NOT NULL 
); 

CREATE OR REPLACE FUNCTION add_artist(_artist CITEXT) RETURNS INTEGER AS $$ 
    DECLARE 
     _artist_id INT; 
    BEGIN 
     SELECT artist_id INTO _artist_id FROM artists WHERE artist = _artist; 

     IF (_artist_id IS NULL) THEN 
      INSERT INTO artists (artist) VALUES (
       _artist 
      ) RETURNING artist_id INTO _artist_id; 
     END IF; 

     RETURN _artist_id; 
    END; 
$$ LANGUAGE plpgsql; 

現在我試圖調用在Java中使用該功能的擴展我以前加載

public int addArtist(String name) throws SQLException { 
    int artist_id; 

    try (CallableStatement callableStatement = 
      connection.prepareCall("{ ? = CALL add_artist(?) }")) { 
     callableStatement.registerOutParameter(1, Types.INTEGER); 
     callableStatement.setString(2, name); 
     callableStatement.execute(); 
     artist_id = callableStatement.getInt(1); 
    } 

    return (artist_id != 0) ? artist_id : -1; 
} 

如果傳遞給sql函數的參數類型爲INTEGERVARCHAR(n),則調用函數中的相同方法可以正常工作。

我認爲callableStatement.setString(2, name);正在拋出SQLException,因爲setString()將被用於VARCHAR(n)字段?

org.postgresql.util.PSQLException: ERROR: function add_artist(character varying) does not exist 
    Hint: No function matches the given name and argument types. You might need to add explicit type casts. 
    Position: 15 
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2182) 
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1911) 
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173) 
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:615) 
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:465) 
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:458) 
at postgresql.PostgreSQL.addArtist(PostgreSQL.java:61) 
at postgresql.PostgreSQLConnector.main(PostgreSQLConnector.java:26) 

CallableStatement有一個像setText(int i, String text)沒有方法 - 我必須使用呢?

回答

4

我終於明白了。我所要做的就是使用::citext將參數轉換爲CITEXT

public int addArtist(String name) throws SQLException { 
    int artist_id; 

    try (CallableStatement callableStatement = 
      connection.prepareCall("{ ? = CALL add_artist(?::citext) }")) { 
     callableStatement.registerOutParameter(1, Types.INTEGER); 
     callableStatement.setString(2, name); 
     callableStatement.execute(); 
     artist_id = callableStatement.getInt(1); 
    } 

    return (artist_id != 0) ? artist_id : -1; 
} 
+1

另一種選擇是將'stringtype = unspecified'設置爲連接參數。 –

+0

有趣,比鑄造更普遍嗎?並且在設置'stringtype = unspecified'並在'prepareCall()'字符串中強制參數之間有區別嗎? – phew

+2

如果你能夠,鑄造是最好的。如果你使用的ORM不能提供這種級別的控制權,那麼傳遞'stringtype = unspecified'會要求PgJDBC將字符串視爲非類型文字,並讓數據庫服務器推斷它們的數據類型。 –

相關問題