JDBCドライバ。PreparedStatement#setNull()とParameterMetaData

たとえば、PostgreSQLでは、下のようなコードでbbalanceカラムがINTEGER型のときに、NULLを設定するためにPreparedStatement#setNull()の第2引数に適当なsqlTypeを指定すると「型がちがうよ」と怒られる。

PreparedStatement ps =
  conn.prepareStatement("update branches set bbalance = ? where bid = 1");
ps.setNull(1, Types.VARCHAR);
ps.executeUpdate();

エラーメッセージはこんなの。

org.postgresql.util.PSQLException: ERROR: column "bbalance" is of type integer but expression is of type character varying

でも、ParameterMetaDataを使って型情報をとれば大丈夫。

PreparedStatement ps =
  conn.prepareStatement("update branches set bbalance = ? where bid = 1");
ParameterMetaData metaData = ps.getParameterMetaData();
int sqlType = metaData.getParameterType(1);
ps.setNull(1, sqlType);
ps.executeUpdate();

ParameterMetaDataは非常に便利だけど、対応していないドライバもあるらしい(Oracleとか)。でもOracleとかでは、PreparedStatement#setNull()に適当なsqlTypeを指定しても大丈夫らしいので、RDBMSごとに方法を変えればいい。フレームワークがこの違いを吸収し、アプリケーション側で型を意識しなくてもいいようにできるといい。

気をつけたいのは、PostgreSQLJDBCドライバではPreparedStatement.getParameterMetaData()をすると毎回データベースとの通信が発生するということ。PreparedStatementを破棄するまではキャッシュできる情報なんだけどね。