現在、Spring Data JPAを利用してて、JPAからの脱却をするとなると現実的な移行方法を考えたときに、Spring Data JDBCが移行先かなと思い検証を実施しました。 レポジトリは、spring-data-jpa-and-jdbcです。
今回の環境
- Java 21 - Spring Boot 3.4.0
検証手順
- Spring Data JPAを利用したアプリケーションの実装 - Spring Data JDBCを依存関係に追加し、Spring Data JPAで実装されている処理と同等の処理を追加
検証
Spring Data JPAを利用したアプリケーションの実装
build.gradleに以下の依存関係を追加します。
dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.mysql:mysql-connector-j' implementation 'org.springframework.boot:spring-boot-starter-web' developmentOnly 'org.springframework.boot:spring-boot-docker-compose' }
次に、以下のER図をものにJPA エンティティを実装します。
@Entity @Table(name = "shop") @EntityListeners(AuditingEntityListener.class) public class JpaShop { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; @CreatedDate @ReadOnlyProperty private Instant createdAt; @LastModifiedDate @ReadOnlyProperty private Instant updatedAt; @OneToMany(mappedBy = "shop") private List<JpaUser> users; // getter, setterは省略 }
@Entity @Table(name = "user") @EntityListeners(AuditingEntityListener.class) public class JpaUser { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; private Integer age; @CreatedDate @ReadOnlyProperty private Instant createdAt; @LastModifiedDate @ReadOnlyProperty private Instant updatedAt; @ManyToOne @JoinColumn(name = "shop_id") private JpaShop shop; // getter, setterは省略 }
設定の追加
@Configuration(proxyBeanMethods = false) @EnableJpaRepositories( basePackages = { "com.b1a9idps.spring_data_jpa_and_jdbc.application.repository.jpa" } ) @EnableJpaAuditing public class JpaConfig { }
あとは、JpaRepository.javaをextendsしたインターフェースを実装して、データアクセスします。
Spring Data JDBCの導入
まず、build.gradleにSpring Data JDBCを追加します
dependencies { // 追加 implementation 'org.springframework.boot:spring-boot-starter-data-jdbc' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.mysql:mysql-connector-j' implementation 'org.springframework.boot:spring-boot-starter-web' developmentOnly 'org.springframework.boot:spring-boot-docker-compose' }
次に、先に実装したJPAエンティティと同等のクラスを実装します。
@Table("shop") public class JdbcShop { @Id private Integer id; private String name; @MappedCollection(idColumn = "shop_id", keyColumn = "shop_id") private List<JdbcUser> users; @CreatedDate @ReadOnlyProperty private LocalDateTime createdAt; @LastModifiedDate @ReadOnlyProperty private LocalDateTime updatedAt; // getter, setterは省略
@Table("user") public class JdbcUser { @Id private Integer id; private String name; private Integer age; private Integer shopId; @CreatedDate @ReadOnlyProperty private Instant createdAt; @LastModifiedDate @ReadOnlyProperty private Instant updatedAt; // getter, setterは省略
設定の追加
@Configuration(proxyBeanMethods = false) @EnableJdbcRepositories( basePackages = { "com.b1a9idps.spring_data_jpa_and_jdbc.application.repository.jdbc" } ) @EnableJdbcAuditing public class JdbcConfig extends AbstractJdbcConfiguration { }
あとは、ListPagingAndSortingRepository.javaをextendsしたインターフェースを実装して、データアクセスします。
Spring Data JPAとSpring Data JDBCを共存させるときの注意点
1. JDBCのエンティティには spring-data-relational
の @Table
を付与する
JDBCのエンティティには spring-data-relational
の @Table
を付与します。付与しない場合は、テーブルにマッピングするクラスを認識されません。
2. エンティティに付与する @Id
アノテーションを間違えない
わかりづらいですが、Spring Data JPAのエンティティには、jakarta.persistence-api
の @Id
を付与し、Spring Data JDBCのエンティティには、spring-data-commons
の@Id
を付与します。
まとめ
Spring Data JDBCははじめて触ったが、Spring Data JDBCは、シンプルで規約に従ったデータ操作を優先しており、JPAのようなJOINや複雑なエンティティリレーションや動的クエリを扱うことを目的としてない設計のため、単体ではあまり使い物にならなず、クエリビルダーとの併用が必須だなと感じた。かなり薄い作りなので学習コストは低いように感じました。
技術選定としては、Spring Data JDBC + JOOQ(クエリビルダーとして)が個人的にはしっくりきました。