package com.example.relationaldataaccess;
public class Customer {
private long id;
private String firstName, lastName;
public Customer(long id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format(
"Customer[id=%d, firstName='%s', lastName='%s']",
id, firstName, lastName);
}
// getters & setters omitted for brevity
}
Spring JDBC JdbcTemplate で SQL 発行
このガイドでは、Spring を使用してリレーショナルデータにアクセスするプロセスを順を追って説明します。
構築するもの
Spring の JdbcTemplate
を使用して、リレーショナルデータベースに保存されているデータにアクセスするアプリケーションを構築します。
必要なもの
約 15 分
Eclipse STS や IntelliJ IDEA のような任意の IDE または VSCode のようなテキストエディター
Java 17 以降
コードを直接 IDE にインポートすることもできます。
本ガイドの完成までの流れ
ほとんどの Spring 入門ガイドと同様に、最初から始めて各ステップを完了するか、すでに慣れている場合は基本的なセットアップステップをバイパスできます。いずれにしても、最終的に動作するコードになります。
最初から始めるには、Spring Initializr から開始に進みます。
基本をスキップするには、次の手順を実行します。
このガイドを Eclipse で「Spring 入門コンテンツのインポート」するか、ソースリポジトリをダウンロードして解凍、または、Git (英語) を使用してクローンを作成します。
git clone https://github.com/spring-guides/gs-relational-data-access.git
gs-relational-data-access/initial
に cdCustomer
オブジェクトを作成するにジャンプしてください。
完了したときは、gs-relational-data-access/complete
のコードに対して結果を確認できます。
Spring Initializr から開始
IDE を使用する場合はプロジェクト作成ウィザードを使用します。IDE を使用せずにコマンドラインなどで開発する場合は、この事前に初期化されたプロジェクトからプロジェクトを ZIP ファイルとしてダウンロードできます。このプロジェクトは、このチュートリアルの例に合うように構成されています。
プロジェクトを手動で初期化するには:
IDE のメニューまたはブラウザーから Spring Initializr を開きます。アプリケーションに必要なすべての依存関係を取り込み、ほとんどのセットアップを行います。
Gradle または Maven のいずれかと、使用する言語を選択します。このガイドは、Java を選択したことを前提としています。
依存関係をクリックし、JDBC API と H2 Database を選択します。
生成をクリックします。
結果の ZIP ファイルをダウンロードします。これは、選択して構成された Web アプリケーションのアーカイブです。
Eclipse や IntelliJ のような IDE は新規プロジェクト作成ウィザードから Spring Initializr の機能が使用できるため、手動での ZIP ファイルのダウンロードやインポートは不要です。 |
プロジェクトを Github からフォークして、IDE または他のエディターで開くこともできます。 |
Customer
オブジェクトを作成する
使用する単純なデータアクセスロジックは、顧客の姓と名を管理します。このデータをアプリケーションレベルで表すには、次のリスト(src/main/java/com/example/relationaldataaccess/Customer.java
から)が示すように、Customer
クラスを作成します。
データの保存と取得
Spring は、JdbcTemplate
と呼ばれるテンプレートクラスを提供し、SQL リレーショナルデータベースと JDBC を簡単に操作できるようにします。ほとんどの JDBC コードは、リソースの取得、接続管理、例外処理、コードの目的とはまったく関係のない一般的なエラーチェックに没頭しています。JdbcTemplate
はあなたのためにそれらすべてを処理します。しなければならないのは、手元のタスクに集中することです。次のリスト(src/main/java/com/example/relationaldataaccess/RelationalDataAccessApplication.java
から)は、JDBC を介してデータを保管および取得できるクラスを示しています。
package com.example.relationaldataaccess;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@SpringBootApplication
public class RelationalDataAccessApplication implements CommandLineRunner {
private static final Logger log = LoggerFactory.getLogger(RelationalDataAccessApplication.class);
public static void main(String args[]) {
SpringApplication.run(RelationalDataAccessApplication.class, args);
}
@Autowired
JdbcTemplate jdbcTemplate;
@Override
public void run(String... strings) throws Exception {
log.info("Creating tables");
jdbcTemplate.execute("DROP TABLE customers IF EXISTS");
jdbcTemplate.execute("CREATE TABLE customers(" +
"id SERIAL, first_name VARCHAR(255), last_name VARCHAR(255))");
// Split up the array of whole names into an array of first/last names
List<Object[]> splitUpNames = Arrays.asList("John Woo", "Jeff Dean", "Josh Bloch", "Josh Long").stream()
.map(name -> name.split(" "))
.collect(Collectors.toList());
// Use a Java 8 stream to print out each tuple of the list
splitUpNames.forEach(name -> log.info(String.format("Inserting customer record for %s %s", name[0], name[1])));
// Uses JdbcTemplate's batchUpdate operation to bulk load data
jdbcTemplate.batchUpdate("INSERT INTO customers(first_name, last_name) VALUES (?,?)", splitUpNames);
log.info("Querying for customer records where first_name = 'Josh':");
jdbcTemplate.query(
"SELECT id, first_name, last_name FROM customers WHERE first_name = ?",
(rs, rowNum) -> new Customer(rs.getLong("id"), rs.getString("first_name"), rs.getString("last_name")), "Josh")
.forEach(customer -> log.info(customer.toString()));
}
}
@SpringBootApplication
は、次のすべてを追加する便利なアノテーションです。
@Configuration
: アプリケーションコンテキストの Bean 定義のソースとしてクラスにタグを付けます。@EnableAutoConfiguration
: クラスパス設定、他の Bean、さまざまなプロパティ設定に基づいて、Bean の追加を開始するよう Spring Boot に指示します。@ComponentScan
:com.example.relationaldataaccess
パッケージの他のコンポーネント、構成、サービスを探すように Spring に指示します。この場合、何もありません。
main()
メソッドは、Spring Boot の SpringApplication.run()
メソッドを使用してアプリケーションを起動します。
Spring Boot は H2(インメモリリレーショナルデータベースエンジン)をサポートし、自動的に接続を作成します。spring-jdbc
を使用しているため、Spring Boot は自動的に JdbcTemplate
を作成します。@Autowired JdbcTemplate
フィールドは自動的にロードし、使用可能にします。
この Application
クラスは Spring Boot の CommandLineRunner
を実装します。これは、アプリケーションコンテキストがロードされた後に run()
メソッドを実行することを意味します。
最初に、JdbcTemplate
の execute
メソッドを使用して DDL をインストールします。
2 番目に、文字列のリストを取得し、Java 8 ストリームを使用して、Java 配列の名 / 姓のペアに分割します。
次に、JdbcTemplate
の batchUpdate
メソッドを使用して、新しく作成したテーブルにいくつかのレコードをインストールします。メソッド呼び出しの最初の引数はクエリ文字列です。最後の引数(Object
インスタンスの配列)は、?
文字があるクエリに代入される変数を保持します。
単一挿入ステートメントの場合、JdbcTemplate の insert メソッドが適切です。ただし、複数の挿入の場合、batchUpdate を使用することをお勧めします。 |
引数に ? を使用して、変数をバインドするよう JDBC に指示することにより、SQL インジェクション攻撃 [Wikipedia] (英語) を回避します。 |
最後に、query
メソッドを使用して、条件に一致するレコードをテーブルで検索します。再び ?
引数を使用してクエリのパラメーターを作成し、呼び出しを行うときに実際の値を渡します。最後の引数は、各結果行を新しい Customer
オブジェクトに変換するために使用される Java 8 ラムダです。
Java 8 ラムダは、Spring の RowMapper などの単一メソッドインターフェースにうまくマッピングされます。Java 7 以前を使用している場合、匿名インターフェース実装をプラグインして、メソッド本体をラムダ式の本体と同じにすることができます。 |
実行可能 JAR を構築する
コマンドラインから Gradle または Maven を使用してアプリケーションを実行できます。必要なすべての依存関係、クラス、リソースを含む単一の実行可能 JAR ファイルを構築して実行することもできます。実行可能な jar を構築すると、開発ライフサイクル全体、さまざまな環境などで、アプリケーションとしてサービスを簡単に提供、バージョン管理、デプロイできます。
Gradle を使用する場合、./gradlew bootRun
を使用してアプリケーションを実行できます。または、次のように、./gradlew build
を使用して JAR ファイルをビルドしてから、JAR ファイルを実行できます。
Maven を使用する場合、./mvnw spring-boot:run
を使用してアプリケーションを実行できます。または、次のように、./mvnw clean package
で JAR ファイルをビルドしてから、JAR ファイルを実行できます。
ここで説明する手順は、実行可能な JAR を作成します。クラシック WAR ファイルを作成することもできます。 |
次の出力が表示されます。
2019-09-26 13:46:58.561 INFO 47569 --- [ main] c.e.r.RelationalDataAccessApplication : Creating tables
2019-09-26 13:46:58.564 INFO 47569 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
2019-09-26 13:46:58.708 INFO 47569 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
2019-09-26 13:46:58.809 INFO 47569 --- [ main] c.e.r.RelationalDataAccessApplication : Inserting customer record for John Woo
2019-09-26 13:46:58.810 INFO 47569 --- [ main] c.e.r.RelationalDataAccessApplication : Inserting customer record for Jeff Dean
2019-09-26 13:46:58.810 INFO 47569 --- [ main] c.e.r.RelationalDataAccessApplication : Inserting customer record for Josh Bloch
2019-09-26 13:46:58.810 INFO 47569 --- [ main] c.e.r.RelationalDataAccessApplication : Inserting customer record for Josh Long
2019-09-26 13:46:58.825 INFO 47569 --- [ main] c.e.r.RelationalDataAccessApplication : Querying for customer records where first_name = 'Josh':
2019-09-26 13:46:58.835 INFO 47569 --- [ main] c.e.r.RelationalDataAccessApplication : Customer[id=3, firstName='Josh', lastName='Bloch']
2019-09-26 13:46:58.835 INFO 47569 --- [ main] c.e.r.RelationalDataAccessApplication : Customer[id=4, firstName='Josh', lastName='Long']
要約
おめでとう! Spring を使用して、単純な JDBC クライアントを開発しました。
Spring Boot には、接続プールを構成およびカスタマイズするための多くの機能があります。たとえば、メモリ内データベースではなく外部データベースに接続するためです。詳細については、リファレンスガイド (英語) を参照してください。 |
関連事項
次のガイドも役立ちます。
新しいガイドを作成したり、既存のガイドに貢献したいですか? 投稿ガイドラインを参照してください [GitHub] (英語) 。
すべてのガイドは、コード用の ASLv2 ライセンス、およびドキュメント用の Attribution、NoDerivatives creative commons ライセンス (英語) でリリースされています。 |