Spring Data JDBCの使い方 – 【Java】
前提
項目 | 値 |
---|---|
プロジェクト | Gradleプロジェクト |
Spring Boot | 3.1.3 |
Language | 17 |
Spring Data JDBCがサポートしているDBです。
- DB2
- H2
- HSQLDB
- MariaDB
- Microsoft SQL Server
- MySQL
- Oracle
- Postgres
build.gradle
build.gradleで1行追加します。
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
CrudRepository
org.springframework.data.repository.CrudRepository
をimplementしたインタフェースを定義します。
findAll()やfindById()、save()やcount()など基本的なCRUDのメソッドが用意されています。
saveAll(),findAll(),findAllById()がIterableを返します。
ListCrudRepository ※ver3以降
org.springframework.data.repository.ListCrudRepository
をimplementしたインタフェースを定義します。
findAll()やfindById()など基本的なCRUDのメソッドが用意されています。
saveAll(),findAll(),findAllById()がListを返します。
PagingAndSortingRepository
ページングをしたい場合はorg.springframework.data.repository.PagingAndSortingRepository
をimplementしたインタフェースを定義します。
findAll()で全検索します。
PagingAndSortingRepository<Employee, Long> repository; Page<Employee> employee = repository.findAll(PageRequest.of(1, 20));
引数にorg.springframework.data.domain.PageRequest
を指定してページングします。
PageRequest.of(ページ数,ページサイズ);
引数 | 値 |
---|---|
第一引数 | ページ数(0基底) |
第二引数 | ページサイズ |
@Query
@Queryアノテーション(org.springframework.data.jdbc.repository.query.Query)を使用してnative queryを使用します。
@Query("SELECT * FROM EMPLOYEE WHERE NAME = :name") List xxx(@Param("name") String name);
Springはorg.springframework.data.repository.query.Param
を省略しても良いようです。
Spring fully supports Java 8’s parameter name discovery based on the -parameters compiler flag. By using this flag in your build as an alternative to debug information, you can omit the @Param annotation for named parameters.
save()メソッド
save()メソッドでインサートとアップデートを行います。@Idを付与したPKがnullの場合、インサートし、設定している場合、その値のデータをアップデートします。
テーブル側のDDLでPKはauto incrementされている必要があります。
ナチュラルキーにしたい場合はPersistableインタフェースをimplementしてisNew()メソッドをオーバーライドして判断する必要があります。
save()メソッド ※Persistable
エンティティにorg.springframework.data.domain.Persistableをimplementsさせて2つのメソッドをオーバーライドします。
- getId()
- isNew()
isNew()メソッドでsave()がインサートかアップデートかをコントロールします。
@Table("USER") @Getter @AllArgsConstructor public class XxxEntity implements Persistable { @PersistenceCreator public XxxEntity(Long id, String name, Integer age) { this.id = id; this.name= name; this.age= age; } @Id @Column("ID") Long id; @Column("NAME") String name; @Column("AGE") Integer age; @Transient boolean isNew; @Override @Nullable public Long getId() { return id; } @Override public boolean isNew() { return isNew; } }
isNewフィールドには@Transientアノテーションを付与することにより永続化対象外のフィールドにします。
コンストラクタに@PersistenceCreatorアノテーションを付与することにより、Spring Data JDBCに使用させるコンストラクタを指定します。※@PersistenceConstructorアノテーションは非推奨
データ生成は@AllArgsConstructorで自動生成したコンストラクタを使用し、isNewにtrue or falseを渡してインサート or アップデートをコントロールします。
XxxEntity entity = new XxxEntity(1L, "tani", 20, true); // trueなのでinsert repo.save(entity); // insertされる XxxEntity entity = new XxxEntity(1L, "tani", 20, false); // falseなのでupdate repo.save(entity); // updateされる
isNew()メソッドを使う場合はPKはauto incrementされている必要がありません。
SQLログ
SQLログをコンソール出力する場合は、application.ymlに以下追記します。
logging: level: org: springframework: jdbc: core: JdbcTemplate: TRACE
1対1のEntity
1対1のテーブルをEntityで表します。
H2のDDLです。
CREATE TABLE PARENT( id INTEGER AUTO_INCREMENT PRIMARY KEY, parent_name TEXT NOT NULL ); CREATE TABLE CHILD( id INTEGER AUTO_INCREMENT PRIMARY KEY, child_name TEXT NOT NULL, parent_id INTEGER UNIQUE, FOREIGN KEY (parent_id) REFERENCES PARENT(id) );
この親子テーブルをエンティティで表します。
Parentテーブルです。
package jp.co.confrage.demo.domain.entity; import org.springframework.data.annotation.Id; import org.springframework.data.relational.core.mapping.Column; public record Parent(@Id Long id, String parentName, @Column("PARENT_ID") Child child) { }
Childテーブルです。PKやFKの定義は不要です。定義した場合は、PK,FKともにnullを設定すれば動作はします。
package jp.co.confrage.demo.domain.entity; public record Child(String childName) { }
Parentのリポジトリインタフェースです。
package jp.co.confrage.demo.infrastructure.repository; import org.springframework.data.repository.ListCrudRepository; import jp.co.confrage.demo.domain.entity.Parent; public interface ParentRepository extends ListCrudRepository<Parent, Long> { }
コントローラを作成してsaveメソッドでインサートします。
package jp.co.confrage.demo.presentation.controller; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import jp.co.confrage.demo.domain.entity.Child; import jp.co.confrage.demo.domain.entity.Parent; import jp.co.confrage.demo.infrastructure.repository.ParentRepository; import lombok.RequiredArgsConstructor; @RestController @RequiredArgsConstructor public class DemoController { private final ParentRepository repo; @RequestMapping(path = "/test", method = RequestMethod.GET) public ResponseEntity<?> read(@RequestHeader HttpHeaders headers) throws Exception { Child child = new Child("takahashi"); Parent parent = new Parent(null, "yamada", child); repo.save(parent); return new ResponseEntity<>(null, headers, HttpStatus.OK); } }
Parentテーブル、Childテーブルに1レコードずつインサートされます。
参考サイト






KHI入社して退社。今はCONFRAGEで正社員です。関西で140-170/80~120万から受け付けております^^
得意技はJS(ES6),Java,AWSの大体のリソースです
コメントはやさしくお願いいたします^^
座右の銘は、「狭き門より入れ」「願わくは、我に七難八苦を与えたまえ」です^^
資格:少額短期保険募集人,FP3級,宅建士
コメント