Web系開発メモ

Java, C#, HTML, CSS, JavaScript のことなどを書いてます。

SpringBoot JPAを使う方法(Spring Data JPA の使用方法)

Spring Boot の Webアプリで、Spring Data JPA を使ってデータにアクセスする方法を書いていきます。

バージョン

使用した製品のバージョンは以下の通りです。

1. ビルドファイルの作成

プロジェクトのフォルダ spring-jpa を作成して、その下に Maven のビルドファイルを作成します。

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.0.1</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <groupId>org.example</groupId>
  <artifactId>spring-jpa</artifactId>
  <version>1.0.0</version>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>17</java.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.postgresql</groupId>
      <artifactId>postgresql</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

依存性に spring-boot-starter-data-jpa を追加すると、Spring Data JPA が使えるようになります。

2. 親エンティティの作成

タイムスタンプの設定を共通化する親クラスを作成します。

src/main/java/org/example/model/TimestampEntity.java

package org.example.model;

import jakarta.persistence.Column;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import lombok.Getter;
import lombok.Setter;

import java.sql.Timestamp;
import java.time.Instant;

@MappedSuperclass // JPAエンティティの親クラスに必要
@Getter @Setter
public abstract class TimestampEntity {
  @Column(name = "update_time")
  private Timestamp updateTime;

  @Column(name = "create_time", updatable = false)
  private Timestamp createTime;

  @PrePersist
  public void prePersist() {
    Timestamp ts = Timestamp.from(Instant.now());
    this.createTime = ts;
    this.updateTime = ts;
  }

  @PreUpdate
  public void preUpdate() {
    this.updateTime = Timestamp.from(Instant.now());
  }
}

SQL を書かないので、Java 側でタイムスタンプを設定します。

3. エンティティの作成

上の親クラスを継承するモデルを作成します。

src/main/java/org/example/model/Student.java

package org.example.model;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Version;
import lombok.Getter;
import lombok.Setter;

@Entity
@Getter @Setter
public class Student extends TimestampEntity {
  @Id
  @GeneratedValue(strategy= GenerationType.IDENTITY)
  private Long id;

  @Column(nullable = false)
  private String name;

  @Version
  @Column(nullable = false)
  private Long version;
}

4. リポジトリの作成

データの操作を行うインターフェイスを作成します。

src/main/java/org/example/repository/StudentRepository.java

package org.example.repository;

import org.example.model.Student;
import org.springframework.data.repository.CrudRepository;

public interface StudentRepository extends CrudRepository<Student, Long> {
}

CrudRepository を継承するだけで、基本的なデータ操作を行うことができます。

また、Spring の命名規約に従ってメソッドを追加すると、WHERE句などの条件を指定することができます。詳細は Spring Data JPA のドキュメント に記載されています。

5. コントローラーの作成

リクエストを受け付けて、リポジトリに処理を委譲するクラスを作成します。

src/main/java/org/example/controller/StudentController.java

package org.example.controller;

import org.example.model.Student;
import org.example.repository.StudentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/students")
public class StudentController {
  @Autowired
  StudentRepository repository;

  @PostMapping
  public Student create(@RequestBody Student student) {
    return repository.save(student);
  }

  @GetMapping("/{id}")
  public Student read(@PathVariable Long id) {
    return repository.findById(id).get();
  }

  @PutMapping("/{id}")
  public Student update(
    @PathVariable Long id, @RequestBody Student student
  ) {
    Student savedStudent = repository.findById(id).get();
    savedStudent.setName(student.getName());
    return repository.save(savedStudent);
  }

  @DeleteMapping("/{id}")
  public void delete(@PathVariable Long id) {
    repository.deleteById(id);
  }
}

※ サービスクラスは省略しています。

6. 起動クラスの作成

アプリを起動するクラスを作成します。

src/main/java/org/example/SpringApp.java

package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringApp {
  public static void main(String[] args) {
    SpringApplication.run(SpringApp.class, args);
  }
}

7. 設定ファイルの作成

PostgreSQL に接続するための設定ファイルを作成します。

src/main/resources/application.properties

spring.datasource.url=jdbc:postgresql://localhost:5432/test
spring.datasource.username=usr
spring.datasource.password=pass

spring.jackson.date-format=yyyy/MM/dd HH:mm:ss
spring.jackson.time-zone=Asia/Tokyo

JSON の日時のフォーマットとタイムゾーン(日本時間)も設定しています。

8. テーブルの作成

アプリを起動する前に、以下の SQL でテーブルを作成します。

CREATE TABLE student (
  id bigserial PRIMARY KEY,
  name varchar(60) NOT NULL,
  version bigint NOT NULL,
  update_time timestamp NOT NULL DEFAULT current_timestamp,
  create_time timestamp NOT NULL DEFAULT current_timestamp
);

9. アプリの起動

起動クラスを実行するか、以下のコマンドでアプリを起動します。

mvn spring-boot:run

10. 動作確認

確認コマンドの JSONエスケープ「\」は、Windows で必要になります。

10.1. データの作成

以下のコマンドで、データを一つ作成します。

curl -H "Content-Type: application/json" -d "{\"name\":\"Jhon Doe\"}" -X POST http://localhost:8080/students

実行すると JSON が返ってきます。

{"updateTime":"2022/12/23 15:56:29","createTime":"2022/12/23 15:56:29","id":1,"name":"Jhon Doe","version":0}

10.2. データの参照

作成したデータを参照することができます。

curl http://localhost:8080/students/1

10.3. データの更新

以下のコマンドで、作成したデータを更新することができます。

curl -H "Content-Type: application/json" -d "{\"name\":\"Jhon Smith\"}" -X PUT http://localhost:8080/students/1

実行すると、更新後の JSON が返ってきます。

{"updateTime":"2022/12/23 15:56:55","createTime":"2022/12/23 15:56:29","id":1,"name":"Jhon Smith","version":1}

10.4. データの削除

作成したデータを削除することができます。

curl -X DELETE http://localhost:8080/students/1