SimpleJdbcTemplateに甘えすぎた

JdbcTemplateのsyntax sugarなSimpleJdbcTemplate。文法が甘いだけに、恥ずかしいエラーで立ち止まる。

SimpleJdbcTemplateで使うのRarameterrizedRowMapper

public class FooRowMapper implements ParameterizedRowMapper {

    @Override
    public Foo mapRow(ResultSet rs, int rowNum) throws SQLException {
        Foo foo = new Foo();
        foo.setId(rs.getInt("ID"));
        foo.setName(rs.getString("NAME"));
        foo.setDate(rs.getDate("DATE"));
        return foo;
    }
}

DAOなクラスFooのDTOであるFooSimpleDTO

public class FooSimpleDTO implements FooService {

    private SimpleJdbcTemplate simpleTemplate;
    
    public void setDataSource(DataSource dataSource) {
        this.simpleTemplate = new SimpleJdbcTemplate(dataSource);
    }

    @Override
    public Foo getFoo(int id) {
        String sql = "select id, name, date from foo where id=?";
        return simpleTemplate.queryForObject(sql, new FooRowMapper(), id);
    }

    @Override
    public int regist(Foo foo) {
        String sql = "insert into foo (id, name, date) values (?, ?, ?)";
        // SQLのパラメータのみを指定するのになぜかRowMapperを指定してる。
        return simpleTemplate.update(sql, new FooRowMapper(), foo.getId(), foo.getName(), foo.getDate());
    }

    // ...
}

実行結果:

There was 1 failure:
1) testFooSimple(examples.jdbc.Tester)
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [insert into foo (id, name, date) values (?, ?, ?)]; SQL state [90026]; error code [90026]; 直列化に失敗しました
Serialization failed, cause: java.io.NotSerializableException: examples.jdbc.FooRowMapper [90026-76]; nested exception is org.h2.jdbc.JdbcSQLException: 直列化に失敗しました
Serialization failed, cause: java.io.NotSerializableException: examples.jdbc.FooRowMapper [90026-76]
 at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.translate(SQLStateSQLExceptionTranslator.java:124)
...

何でRowMapperをシリアライズしてるんだ?と思いつつFooRowMapperをSerializableにして再度実行すると、

There was 1 failure:
1) testFooSimple(examples.jdbc.Tester)
org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; uncategorized SQLException for SQL [insert into foo (id, name, date) values (?, ?, ?)]; SQL state [90008]; error code [90008]; パラメータ parameterIndex に対する値 4 が不正です
Invalid value 4 for parameter parameterIndex [90008-76]; nested exception is org.h2.jdbc.JdbcSQLException: パラメータ parameterIndex に対する値 4 が不正です
Invalid value 4 for parameter parameterIndex [90008-76]
 at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.translate(SQLStateSQLExceptionTranslator.java:124)
...

ここで変なところにRowMapperを指定していることに気がつく。実行時にあからさまにエラーになるからまだ良いけど、コンパイル時にエラーにならない

update(String sql, Object... args)

見たいな Object... には注意注意。そもそもJavaDocちゃんと読まないと…。

p.s. H2ってPreparedStatementのパラメータをシリアライズしてるのね。