バージョン
- Spring Framework 6.1
- Spring Boot 3.2
JdbcClientって?
Spring Framework 6.1(対応するSpring Bootは3.2)からJdbcClientインタフェースが導入されました。
内部的にはJdbcTemplateおよびNamedParameterJdbcTemplateのラッパーです。
流れるようなインタフェース(Fluent API)が特徴です。
Optionalが使いやすい
JdbcTemplateで主キー検索してその結果を何かのクラスのOptionalにしたい場合、👇のようにちょっと面倒でした。
JdbcTemplateでOptionalを返す例
public Optional<Hoge> selectById(Integer id) {
try {
Hoge hoge = jdbcTemplate.queryForObject("""
SELECT id, name
FROM hoge WHERE id = ?
""", new DataClassRowMapper<>(Hoge.class), id);
return Optional.of(hoge);
} catch (EmptyResultDataAccessException e) {
return Optional.empty();
}
}
これがJdbcClientだと👇のように書けます。
JdbcClientでOptionalを返す例
public Optional<Hoge> selectById(Integer id) {
Optional<Hoge> hogeOp = jdbcClient.sql("""
SELECT id, name
FROM hoge WHERE id = ?
""")
.param(id)
.query(new DataClassRowMapper<>(Hoge.class))
.optional();
return hogeOp;
}
例外をキャッチする必要が無いのでスッキリですね!
KeyHolderが使いやすい
INSERTした時にDBで自動生成された主キー値(PostgreSQLのシーケンスなどが使われている場合)を取得するにはKeyHolderを使う必要があります。JdbcTemplateの場合、PreparedStatementを操作する必要があって面倒でした。
JdbcTemplateでKeyHolderを使う例
public Hoge insert(Hoge hoge) {
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(connection -> {
PreparedStatement statement = connection.prepareStatement("""
INSERT INTO hoge(name)
VALUES(?)
""", new String[]{"id"});
statement.setString(1, hoge.name());
return statement;
}, keyHolder);
int newId = keyHolder.getKey().intValue();
return new Hoge(newId, hoge.name());
}
JdbcClientではupdate()の引数にKeyHolderと主キー列名を渡すだけで済みます。主キー列名が配列ではなく可変長引数になっているのも嬉しいですね!
JdbcClientでKeyHolderを使う例
public Hoge insert(Hoge hoge) {
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcClient.sql("""
INSERT INTO hoge(name)
VALUES(?)
""")
.param(hoge.name())
.update(keyHolder, "id");
int newId = keyHolder.getKey().intValue();
return new Hoge(newId, hoge.name());
}