Accessing Data with JPA


Getting Started · Accessing Data with JPA

このガイドでは Spring Data JPA を使い、リレーショナルデータベースにデータを保存し取得する方法を見ていきます。

What you’ll build

POJO な Customer をインメモリデータベースに保存するアプリケーションを作成していきます。

What you’ll need

How to complete this guide

以下から雛形をダウンロードできます。

git clone https://github.com/spring-guides/gs-accessing-data-jpa.git

が、ここではスクラッチで Gradle 使って進めることにします。

Build with Gradle

プロジェクト用のディレクトリを用意して、その中にソースディレクトリ作成します。

mkdir -p src/main/java/hello

build.gradle 作成していきます。

touch build.gradle

内容は以下。

buildscript {
    repositories {
        maven { url "https://repo.spring.io/libs-release" }
        mavenLocal()
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.10.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'

jar {
    baseName = 'gs-accessing-data-jpa'
    version =  '0.1.0'
}

repositories {
    mavenLocal()
    mavenCentral()
    maven { url "https://repo.spring.io/libs-release" }
    maven { url "https://repository.jboss.org/nexus/content/repositories/releases" }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("com.h2database:h2")
    testCompile("junit:junit")
}

task wrapper(type: Wrapper) {
    gradleVersion = '1.11'
}

h2 の依存を追加しています。 starter として spring-boot-starter-data-jpa を指定しています。

spring-boot-gradle-plugin が以下の面倒を見てくれます。

必要な jar あつめて fat-jar を作る main メソッド見つけてjar のマニフェストに自動的に書いて実行可能jarにする Spring Boot の依存を(書き換えることもできるけど)勝手に設定する

Define a simple entity

本例では、JPA エンティティとしてアノテートされた Customer オブジェクトを保存します。

クラスファイルを作成し、

touch src/main/java/hello/Customer.java

以下のようにします。

package hello;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Customer {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
    private String firstName;
    private String lastName;

    protected Customer() {}

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    @Override
    public String toString() {
        return String.format(
                "Customer[id=%d, firstName='%s', lastName='%s']",
                id, firstName, lastName);
    }

}

3つの属性を持つ Customer クラスを定義しました。それぞれ、idfirstName そして lastName です。

コンストラクタは2つあります。デフォルトコンストラクタJPA で必要となります。直接このコンストラクタを操作させたくないので、protected としてあります。 もう片方のコンストラクタはデータベースに保存する Customerインスタンスを生成するために使います。

このガイドでは簡素性のために定型的な getter と setter は省略しています。

Customer クラスは @Entity としてアノテートされており、JPA はこれによりエンティティを識別します。 @Table アノテーションがないため、このエンティティは Customer という名前でエンティティにマップされます。

Customer の id プロパティは @Id としてアノテートされており、JPAはこれをオブジェクトIDとして認識します。そして id プロパティには @GeneratedValue アノテーションも付いており、これにより ID は自動的に生成されます。

残りの2つのプロパティであるfirstNamelastName にはアノテーションはありません。これらのプロパティはプロパティ名と同じ名前でカラムとしてマッピングされます。

toString() メソッドは customer のプロパティを出力します。

Create simple queries

Spring Data JPAJPA を使ってリレーショナルデータベースにデータを格納することに焦点を当てています。 最も魅力的な機能は、リポジトリインターフェースから実行時に自動的に実装を作成する機能です。

リポジトリインターフェースを作成し、どのように動作するのか見てみましょう。

クラスファイルを作成し、

touch src/main/java/hello/CustomerRepository.java

以下のようにします。

package hello;

import java.util.List;

import org.springframework.data.repository.CrudRepository;

public interface CustomerRepository extends CrudRepository<Customer, Long> {

    List<Customer> findByLastName(String lastName);
}

CustomerRepositoryCrudRepository インターフェースを継承しています。エンティティの型として Customer 、IDの型として LongCrudRepositoryジェネリックパラメータとして指定しています。 CrudRepository を継承することによって、Customer の永続化のためのいくつかのメソッドが引き継がれます。これは、Customer エンティティの保存と削除と検索のためのメソッドとなります。

Spring Data JPA では、簡単なメソッドシグネチャを宣言することで、クエリメソッドとして定義されます。ここでのケースだとfindByLastName() メソッドがそれにあたります。

典型的なJavaアプリケーションでは CustomerRepository の実装クラスを書くとこれですが、Spring Data JPA ではリポジトリインターフェースの実装を書く必要がありません。アプリケーションの実行時に実装が作成されるのです。

組み上げてどのようになるか見てみましょう。

Create an Application class

Application クラスを作成します。

touch src/main/java/hello/Application.java

中身は、

package hello;

import java.util.List;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {

        ConfigurableApplicationContext context = SpringApplication.run(Application.class);
        CustomerRepository repository = context.getBean(CustomerRepository.class);

        // save a couple of customers
        repository.save(new Customer("Jack", "Bauer"));
        repository.save(new Customer("Chloe", "O'Brian"));
        repository.save(new Customer("Kim", "Bauer"));
        repository.save(new Customer("David", "Palmer"));
        repository.save(new Customer("Michelle", "Dessler"));

        // fetch all customers
        Iterable<Customer> customers = repository.findAll();
        System.out.println("Customers found with findAll():");
        System.out.println("-------------------------------");
        for (Customer customer : customers) {
            System.out.println(customer);
        }
        System.out.println();

        // fetch an individual customer by ID
        Customer customer = repository.findOne(1L);
        System.out.println("Customer found with findOne(1L):");
        System.out.println("--------------------------------");
        System.out.println(customer);
        System.out.println();

        // fetch customers by last name
        List<Customer> bauers = repository.findByLastName("Bauer");
        System.out.println("Customer found with findByLastName('Bauer'):");
        System.out.println("--------------------------------------------");
        for (Customer bauer : bauers) {
            System.out.println(bauer);
        }

        context.close();
    }

}

設定のために @EnableAutoConfiguration アノテーションを加える必要があります。このアノテーションは Spring Boot に 現在のパッケージからJPA リポジトリとエンティティの設定を指示します。 org.springframework.data.repository.Repository を継承したインターフェースは実装が自動的に生成されます。JpaRepository はこのインターフェースを継承しているため、先ほど作成した CustomerRepository は Spring Data JPA が見つけて実装を生成します。

Applicationmain() メソッドには CustomerRepository の動作を確認するコードがあります。 最初に Spring のアプリケーションコンテキストから CustomerRepository を取得し、Customer オブジェクトを save() メソッドで保存します。 次に findAll() にてデータベースから全ての Customer オブジェクトを取得します。 そして、findOne() にて単一の Customer を ID で取得します。 最後に findByLastName() にて "Bauer" という名前で Customer を取得します。

Build an executable JAR

Gradle を使っているなら、アプリケーションの実行は ./gradlew bootRun とするだけです。

実行可能 jar を作成するには以下のようにし(初回のみgradle wrapperが必要)、

./gradlew build

jar を実行すればアプリケーションが起動します。

java -jar build/libs/gs-accessing-data-jpa-0.1.0.jar

実行すると以下のような出力が得られるでしょう。

== Customers found with findAll():
Customer[id=1, firstName='Jack', lastName='Bauer']
Customer[id=2, firstName='Chloe', lastName='O'Brian']
Customer[id=3, firstName='Kim', lastName='Bauer']
Customer[id=4, firstName='David', lastName='Palmer']
Customer[id=5, firstName='Michelle', lastName='Dessler']

== Customer found with findOne(1L):
Customer[id=1, firstName='Jack', lastName='Bauer']

== Customer found with findByLastName('Bauer'):
Customer[id=1, firstName='Jack', lastName='Bauer']
Customer[id=3, firstName='Kim', lastName='Bauer']