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ごとに方法を変えればいい。フレームワークがこの違いを吸収し、アプリケーション側で型を意識しなくてもいいようにできるといい。
気をつけたいのは、PostgreSQLのJDBCドライバではPreparedStatement.getParameterMetaData()をすると毎回データベースとの通信が発生するということ。PreparedStatementを破棄するまではキャッシュできる情報なんだけどね。