TwitterやJavaのオープンチャットででたまーにResultSet
から直接LocalDateTime
やBigInteger
を取得できずに、一旦String
やjava.sql.Date
で取得した後に変換している、ということを見かけることがありました。直接LocalDateTimeやBigIntegerで取得することができます。
今回の記事では、DBからJavaのResultSetを駆使し、JdbcTemplate#query
にてLocalDateTime
とBigInteger
を取得する方法を記載します。
環境
- Java
- 15
- org.springframework.boot
- 2.5.2
- org.flywaydb:flyway-core
- 7.7.3
- com.h2database:h2
- 2.1.2.200
- org.springframework.boot:spring-boot-starter-test
- 2.5.2
- org.springframework.boot:spring-boot-starter-jdbc
- 2.5.2
- org.mybatis.spring.boot:mybatis-spring-boot-starter
- 2.2.0
- org.mybatis.spring.boot:mybatis-spring-boot-starter-test
- 2.2.0
- Gradle
ゴール
JavaのJdbcTemplate#query
にてRLocalDateTime
とBigInteger
を取得します。
要約
ResultSet
のgetObject
の第二パラメータに必要なクラスを指定します。
方法
事前準備
テーブルとデータを準備します。
CREATE TABLE BOOK ( isbn VARCHAR(13) PRIMARY KEY, money INT, number INT, generate_date TIMESTAMP ); INSERT INTO BOOK VALUES ('9784798126708', 1000, 10, '2021-07-02 12:34:56')
取得用のDtoを作成する
jdbcTemplate
から取得するための型を用意します。
@Data @Builder @NoArgsConstructor @AllArgsConstructor public class BookDto implements Serializable { private String isbn; private int money; private BigInteger number; private LocalDateTime generateDate; }
Javaで取得する
JdbcTemplate#query
を使用します。ResultSet
のgetObject
の第二パラメータに必要なクラスを指定します。
今回の場合は、BigInteger.class
, LocalDateTime.class
を指定することができます。
protected List<BookDto> findBookList() { return jdbcTemplate.query("SELECT * FROM BOOK", (rs, i) -> BookDto.builder() .isbn(rs.getString("isbn")) .money(rs.getInt("money")) .number(rs.getObject("number", BigInteger.class)) .generateDate(rs.getObject("generate_date", LocalDateTime.class)) .build()); }
備考
単純にラップした自作型に関してはマッピングできないようです。ISBN
クラスを作成してマッピングしようとしましたが、エラーログが出力されました。
@Data @Builder @NoArgsConstructor @AllArgsConstructor public class BookDto implements Serializable { private Isbn isbn; private int money; private BigInteger number; private LocalDateTime generateDate; } @Value @AllArgsConstructor public class Isbn { private final String isbn; } protected List<BookDto> findBookList() { return jdbcTemplate.query("SELECT * FROM BOOK", (rs, i) -> BookDto.builder() .isbn(rs.getObject("isbn", Isbn.class)) .money(rs.getInt("money")) .number(rs.getObject("number", BigInteger.class)) .generateDate(rs.getObject("generate_date", LocalDateTime.class)) .build()); }
Caused by: org.h2.jdbc.JdbcSQLFeatureNotSupportedException: 機能はサポートされていません: "kirimaru.biz.domain.book.Isbn" Feature not supported: "kirimaru.biz.domain.book.Isbn" [50100-200]
素直に構造に合わせたRowMapper
を作成しましょう。
.isbn(new Isbn(rs.getString("isbn"))
ソースコード
単体テストも行えるようにしています。セットアップのためのFlyway等は今回の記事では解説しません。
- https://github.com/hirotoKirimaru/cucumber-sample/blob/811c5050607e3985489d8f001ec93dfff4f6184d/kirimaru-repository/src/main/java/kirimaru/biz/mapper/dto/BookDto.java
- https://github.com/hirotoKirimaru/cucumber-sample/blob/e4c99f942451a806e4f60a4be8aceb2549a6e4c2/kirimaru-repository/src/test/java/kirimaru/biz/mapper/helper/CommonSetup.java#L35-L47
- https://github.com/hirotoKirimaru/cucumber-sample/blob/811c5050607e3985489d8f001ec93dfff4f6184d/kirimaru-repository/src/test/java/kirimaru/biz/mapper/BookMapperTests.java#L41-L60
終わりに
地味ながら、低くない頻度で見かけるので記事にしました。
やってることは簡単なので、困っている人に届くと嬉しいです。
この記事がお役に立ちましたら、各種SNSでのシェアや、今後も情報発信しますのでフォローよろしくお願いします。