Spring BootでMySQL接続してSpring DATA JPAでデータを取得

前回、Spring Frameworkを導入してみました。そして、Spring BootでWeb(Spring MVC)とThymeleafを実際に利用してみました。今回は、Spring DATA JPAという機能を使ってデータベースとのデータをやり取りしてみたいと思います。

データベースには、MySQLを使っていきたいと思いますのでインストールしてない人は、インストールしておきましょう。

 

MySQLインストール

MySQLのダウンロード&インストールと初期設定方法 | サービス | プロエンジニア

Windows 10 HomeにMySQL 5.7.18を単体でインストール

 

JPAJava Persistence API)って?

そもそも、JPAJava Persistence API)って何なのさ?となり、

JPAJava Persistence APIの略です。永続化およびオブジェクトとリレーショナルのマッピング管理用のJava APIの仕様です。Java EE環境に限らず、Java SEでも利用可能です。

JPA 2.0入門 | Oracle WebLogic Channel Blog

や、

JPAは、JSRで定義されているJava標準技術の1つ(JSR338: Java Persistence API 2.1)です。つまり、Java言語の世界では、データベース利用の標準技術ということですね。

データベースを簡単にーJavaSEでもオブジェクト指向データベース(JPA) - Qiita

Java Persistence APIは、永続的にオラクル社が提供するデータベースに膨大な量のデータを格納するためのクラスとメソッドのコレクションです。

JPAクイックガイド

ということらしく、データベースに関わってくるようです。

具体的には、データベースのテーブルのレコードとJavaのオブジェクト間の 相互変換を行います。それにより、アプリケーション開発者がJavaのオブジェクトにアクセスすると、 その結果データベースへの操作が行われます。

JPA 2.0入門 | Oracle WebLogic Channel Blog

JPAのイメージ図(すみません、かなりあやふやです)

f:id:ts0818:20170909102518p:plain

5.2. データベースアクセス(JPA編) — TERASOLUNA Global Framework Development Guideline 1.0.0.publicreview documentation

⇧  こちらのサイト様が詳しく仕組みを紹介しているので、JPAの仕組みについてはこちらのサイトを参考ください。


さらに具体的に、 

Persistenceは、永続性とか持続性などという意味なので、オブジェクトをそのままの形で永続的に保管したり、取り出したりするためのAPIという意味です。

同じようなことは、ObjectInputStreamやObjectOutputStreamを使ってもできます。これらを使うと、オブジェクトをファイルに保管することができます。

しかし、JPAはファイルではなく、データベースに保管するところが大きな違いです。簡単なJava言語のメソッドだけで操作できるので、従来のように、JDBCSQLを使う必要はありません。

データベースを簡単にーJavaSEでもオブジェクト指向データベース(JPA) - Qiita

JDBCドライバが必要ないということですかね? 

Spring Boot/第三回 Spring Bootでデータベース操作(JPA編) - なべ’s blog

⇧ 上記サイトによりますと、データベースの操作には、

2種類があり、JavaのORマッピングの仕様「JPAJava Persistence APIJavaの永続化のAPI)」でデータベースを操作する場合、JDBCではないのでJDBCドライバは必要なさそうです。

と思ったけど、

5.2. データベースアクセス(JPA編) — TERASOLUNA Global Framework Development Guideline 1.0.0.publicreview documentation

によりますと、JDBC使ってるっぽい...すみません、このへんちょっと分らんです。

 

データベースの世界とオブジェクトの世界とは、水と油ほども違うので、両者のつじつま合わせをする技術(ORM: Object Relational Mapping)の理解も必要ですが、それも今では、簡単なアノテーションソースコードに書き加えるだけでいいことになっているので、簡単です。

データベースを簡単にーJavaSEでもオブジェクト指向データベース(JPA) - Qiita

アノテーションをつけることで、ORM(Javaのオブジェクトとデータベースのテーブルの相互変換) を行ってくれるようです。

JPAは仕様であって、実際にはベンダーがJPAを実装していて、提供されているものをJPAプロバイダというようです。

JPAの実装は、HibernateのようなO/R Mapperを開発しているベンダーによって、参照実装として提供されている。 このように、O/R Mapperを開発しているベンダーによって実装された参照実装のことを、JPAプロバイダと呼ぶ。

5.2. データベースアクセス(JPA編) — TERASOLUNA Global Framework Development Guideline 1.0.0.publicreview documentation

JPAプロバイダとしては、

などがあるみたいです。Spring DATA JPAはデフォルトだと内部的にHibernateで実装されているみたいです。

Spring Data JPAのJPA実装をHibernateからEclipseLinkに変更する

⇩  EclipseLink、Hibernateでできることが違うようです。 

わかりやすいJPA - いくつものJava

 

Spring DATA JPA

Spring用のJPAライブラリのようです。Springでデータベースと連携する際は、これを使ってといて~、みたいな感じですかね? 

 

Spring Data – すべてのデータストアに対応するAPI?

⇧  によると、Spring DATAの中の1つがSpring DATA JPAっぽい感じですかね。

 

Spring Frameworkでも、JPAを利用してデータベースアクセスを行う「Spring Data JPA」というライブラリが用意されています。これは「Spring Data」と呼ばれるデータベースアクセス関連ライブラリの一つです。

この他に、非SQLであるMongoDBを利用する「Spring Data MongoDB」や、Hadoop利用のための「Spring Data Hadoop」などといったものが用意されています。

Spring Data JPAは、一般的なSQLによるリレーショナルデータベース全般を利用するためのもので、Spring Dataの基本となるライブラリといっていいでしょう。

Spring Data JPAの利用(1/7):初心者のためのSpring Framework入門

Spring DATA JPA概要 · GitHub

 

Spring BootでJPAを利用するには、「pom.xml」に、「spring-boot-starter-data-jpa」とMySQLを使う場合は「mysql-connector-java」を追加します。

50分で分かるSpring Data JPA/spring-data-jpa-in-50min // Speaker Deck

⇧  Spring Bootでない場合は、「hibernate-entitymanager」というものも必要になってくるようです。

 

Eclipse(「STSプラグイン」の入った)を起動し、プロジェクトの中の「pom.xml」を開きます。下の方にあるタブで「依存関係」を選択。

f:id:ts0818:20170909102519j:plain

「依存関係」の「追加...」をクリック。

f:id:ts0818:20170909102520j:plain

「spring-boot-starter-data-jpa」を検索、選択し、「OK」。

f:id:ts0818:20170909102521j:plain

同じ流れで、「mysql-connector-java」も検索、選択し「OK」。

f:id:ts0818:20170909102522j:plain

「依存関係」に追加されたら「Ctrl + S」でファイルを保存します。

f:id:ts0818:20170909102523j:plain

すみません、今回は、「lombok」というものも追加しておきます。これを追加すると、@Dataアノテーションにて、各フィールドのアクセッサ(getterやsetter)メソッドを、@NoArgsConstructorで引数無しコンストラクター、@AllArgsConstructorですべてのフィールドを引数としたコンストラクターをそれぞれ自動生成してくれるようになるそうです。

Lombok - @Data - 覚えたら書く

Lombok - @Data (2) - 覚えたら書く

Lombok - @Getter / @Setter - 覚えたら書く

lombok を使うには、まずlombok自体をインストールしておく必要があるようです。(「pom.xml」の依存関係だけではダメみたいです...このへんの説明が少なくハマりました。公式サイト見ないと駄目ですね...。)

Spring Boot lombok | Professional Programmer

Project Lombok

f:id:ts0818:20170910073839j:plain

なので、まずは、

https://projectlombok.org/download にアクセスし、「Download 1.16.18」というリンクをクリック。(バージョンを選びたい場合は、「older version」のリンクをクリック。)

f:id:ts0818:20170910072330j:plain

ダウンロードされた「lombok.jar」というファイルをクリックします。「lombok」のインストーラーが起動するので、「Install / Update」をクリックします。(「Quick Installer」でも良いのかもしれないですが、検証してないです。)

f:id:ts0818:20170910073836j:plain

「Install successful」と表示されたら、「×」で閉じてOKです。

IDE(自分の場合だとEclipse)を再起動しろとあるので、Eclipseを再起動します。

f:id:ts0818:20170910073833j:plain

Eclipseを再起動したら、 「pom.xml」を開いて、「依存関係」の「追加...」をクリック。

f:id:ts0818:20170909102545j:plain

「org.projectlombok  lombok」を追加します。

f:id:ts0818:20170909102546j:plain

「>」をクリックすると、バージョンが選べるようになるので、インストールした「lombok」のバージョンに合わせます。「OK」をクリック。

f:id:ts0818:20170910074454j:plain

そしたら、「Ctrl + S」で保存しましょう。

f:id:ts0818:20170909102547j:plain

これで、「lombok」が使えるようになるはずです。


 

データベース接続設定

Spring DATA JPAでデータベース接続する場合、データベース接続の設定は、「src/main/resources/」にある「application.properties」ファイルに記載するか、「src/main/resources/」に「application.yml」を作成して記載するか選べるようです。

その前に、データベースとテーブルを作成しておきます。コマンドプロンプトを起動しMySQLにログインします。

mysql -u root -p

データベースを作成し、データベースを選択し、テーブル作成し、データを入れておきます。

CREATE DATABASE sample;
USE sample;
CREATE TABLE user(
  id int(11) NOT NULL auto_increment,
  name VARCHAR(20),
  PRIMARY KEY(id)
);
INSERT INTO user (name) VALUES('ユーザー名');
SELECT * FROM user;

 

f:id:ts0818:20170909102524j:plain

それでは、データベースの接続設定を記述します。今回は、デフォルトで用意されている「application.properties」ファイルに記載していきます。 

f:id:ts0818:20170910085453j:plain

「username」「password」は各自の設定に合わせてください。今回はrootユーザーを利用してますが、他のユーザーを使う場合は、データベースに対して、権限の設定が必要です。

権限の設定(GRANT文) - ユーザーの作成 - MySQLの使い方

spring.datasource.url=jdbc:mysql://localhost:3306/sample
spring.datasource.username=root 
spring.datasource.password=root
spring.datasource.driverClassName=com.mysql.jdbc.Driver

#SQLのログの出力
logging.level.org.hibernate.SQL=debug
logging.lovel.org.hibernate.type.description.sql.BasicBinder=\trace

#SQLログを読みやすくする
spring.jpa.propaties.hibernate.format_sql=true

50分で分かるSpring Data JPA/spring-data-jpa-in-50min // Speaker Deck

⇧  参考にさせていただいたんですが、今回、特にhibernateを入れた覚えがないのでもしかしたら、SQLのログ出力のところは機能しないかもです。

 

 

設定できましたら、

を作成していきます。まずは、それぞれのフォルダ(パッケージ)を作成。

「パッケージ・エクスプローラー」の「src/main/java」直下のパッケージを選択した状態で、「新規(W)」>「フォルダー」を選択。

f:id:ts0818:20170909102525j:plain

「フォルダー名(N)」を入力し、「完了(F)」。

f:id:ts0818:20170909102526j:plain

同じ流れで、それぞれフォルダを作成します。(フォルダ名は分かりやすければ大丈夫かと。)

f:id:ts0818:20170909102527j:plain

まずは、「repository」インターフェイスから作成。「新規(W)」>「インターフェイス」を選択。

f:id:ts0818:20170909102528j:plain

「名前(M):」を入力し、「拡張インターフェイス(I)」の「追加(A)...」をクリック。

f:id:ts0818:20170909102529j:plain

「JpaRepository」を検索し、選択し「OK」をクリック。

f:id:ts0818:20170909102530j:plain

「拡張インターフェイス(I)」が追加されたら「完了(F)」。

f:id:ts0818:20170909102531j:plain

ファイルにエラーは出ますが、後で編集していきます。

次に、「Entity」クラスを作成。「新規(W)」>「クラス」を選択。

f:id:ts0818:20170909102532j:plain

「名前(M):」を入力し、「インターフェイス(I):」の「追加(A)...」をクリック。

f:id:ts0818:20170909102533j:plain

「Serializable」を検索、選択し「OK」。

f:id:ts0818:20170909102534j:plain

インターフェイス(I):」が追加できたら「完了(F)」をクリック。

f:id:ts0818:20170909102535j:plain

次に「Service」クラスを作成。「新規(W)」>「クラス」を選択。

f:id:ts0818:20170909102536j:plain

「名前(M):」を入力し、「完了(F)」をクリック。

f:id:ts0818:20170909102537j:plain

最後に、「Controller」クラスを作成。

f:id:ts0818:20170909102538j:plain

「名前(M):」を入力し、「完了(F)」。

f:id:ts0818:20170909102539j:plain

表示用のhtmlファイルも作成しておきます。「src/main/resource」の「新規(W)」>「その他(O)...」を選択。

f:id:ts0818:20170909102540j:plain

「Web」>「HTMLファイル」を選択し、「次へ(N)>」をクリック。

f:id:ts0818:20170909102541j:plain

「ファイル名(M):」を入力し、「次へ(N)>」をクリック。

f:id:ts0818:20170909102542j:plain

「完了(F)」をクリック。

f:id:ts0818:20170909102543j:plain

htmlファイルができました。

f:id:ts0818:20170909102544j:plain


 

ファイルの編集

Entityクラス(User.java

クラスに@Entityと、フィールドに 主キーは必須のようで主キーには@Idをつける必要があるようです。(主キーないテーブルとかどうすればいいんでしょうね?)

MySQLで主キー制約を設定する「PRIMARY KEY」 | UX MILK

⇧  主キーは、MySQL だとPRIMARY KEYのついてるものらしいです。

⇩  他のEntityに対するアノテーションは下記サイトへ 

JPA関連アノテーションの基本として-その1- - A Memorandum

@GeneratedValueを使って主キーを生成する方法 - Qiita

package com.example.demo.Entity;

import java.io.Serializable;

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

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(nullable = false)
	private Integer id;
	private String name;

}

Repositoryクラス(UserRepository.java

基本的には、JpaRepositoryインターフェイスを継承しておけば問題ない?ようですかね。

JpaRepository と CrudRepository の違いって何? - Qiita

JpaRepositoryインターフェイスを継承したインターフェイスを作成すると、基本的なCRUD処理(SELECT、INSERT、UPDATE、DELETEなど)が自動生成されるようです。@Repositoryは必要ないみたいです。

50分で分かるSpring Data JPA/spring-data-jpa-in-50min // Speaker Deck

package com.example.demo.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.example.demo.Entity.User;

public interface UserRepository extends JpaRepository<User, Integer> {

}

Serviceクラス(UserService.java

Repositoryインターフェイスを利用して、実際のSQLの処理を行っていくのがServiceクラスの役目らしいです。(イメージ的にはDAOクラスみたいな感じですかね?)

@Autowiredアノテーションをつけることで、newしなくても利用できます。これによってUserRepositoryはインターフェイスであるので、本来ならクラスに継承させインスタンス化させることが必要ですが、そうしたことをしなくてもUserRepositoryのメソッドが利用できるようです。

DI(Dependecy Injection)、日本語でいうところの「依存性の注入」を、@Autowiredアノテーションで実現してるようです。

package com.example.demo.Service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.Entity.User;
import com.example.demo.repository.UserRepository;

@Service
public class UserService {

	@Autowired
	UserRepository repository;

	public User search(Integer id) {
		User user = repository.findOne(id);
		return user;
	}

}

Controllerクラス(UserController.java

@Controllerをつけることで、View側のhtmlファイルを返してくれるようになります。

Spring Boot解説第18回(基本編:Controllerとは) - Qiita

⇧  によりますと、他にも@RestControllerというものがあり、こちらはJSONXML などを返すときに利用していくようです。

@RequestMappingで遷移先を指定してます。(「http://localhost:8080/user」でアクセスされたときに、ここのクラスに処理がやってくる感じです。)

@Autowiredは、Serviceのところでも使われていたのですが、クラスにも使えるようです。

@RequestMapping(method=RequestMethod.GET)でGETの場合、@RequestMapping(method=RequestMethod.POST)でPOSTの場合というように処理を分けれるようです。

【Spring MVC】@RequestMapping の基本 - 山崎屋の技術メモ

ModevAndViewを使用するとViewに渡したい情報を一緒に返すことができる。

Spring MVCのコントローラでの戻り値いろいろ - Qiita

    
package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.example.demo.Entity.User;
import com.example.demo.Service.UserService;

@Controller
@RequestMapping("/user")
public class UserController {

	private static final String VIEW = "user";

	@Autowired
	public UserService service;

	@RequestMapping(method = RequestMethod.GET)
	public String index() {
		return VIEW;
	}

	@RequestMapping(method = RequestMethod.POST)
	public ModelAndView userList(ModelAndView mov, @RequestParam("userId") String userId) {

		mov.setViewName(VIEW);
		User user = service.search(Integer.parseInt(userId));
		mov.addObject("user", user);
		return mov;
	}

}

View側(user.html)

Thymeleaf はxmlとして扱われる?ようなので、必ず閉じが必要になります。<form></form>のように閉じタグがあるものは良いのですが、<meta charset="UTF-8">のような閉じタグがないものは、<meta charset="UTF-8" />のように末尾に「/」を加えないと実効後、エラーが出ます。

<input>タグも同じように末尾に「/」を入れるように注意しましょう。

lombok」を使うと「${user.id}」のようにして「フィールド」の値が取得できるようです。

    
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
<title>SPRING DATA JPA</title>
</head>
<body>
  <form method="POST" name="form">
    ユーザーID: <input type="text" name="userId" value="" />
    <input type="submit" value="検索" />
  </form>

  <div th:if="${user != null}">
    <p th:text="${user.id}"></p>
    <p th:text="${user.name}"></p>
  </div>

</body>
</html>

Entityクラス(User.java)を開いて、「ビュー」の「アウトライン」見ると、アノテーションによって、アクセッサ(getterやsetter)メソッドとコンストラクターが存在しているのが分かります。 (「アウトライン」はEclipse上部の「ウィンドウ(W)」>「ビューの表示(V)」>「アウトライン」から開けます。)

f:id:ts0818:20170910075748j:plain

実際にサーバーで実行してみます。プロジェクトを選択した状態で右クリックし、「実行(R)」>「Spring Boot アプリケーション」を選択。(2回目からは普通の実行ボタンのほうでもいけます。)

f:id:ts0818:20170910101453j:plain

http://localhost:8080/user」にアクセス。

f:id:ts0818:20170910080851j:plain

userテーブルに登録されているidが1なので、1を入力すると、

f:id:ts0818:20170910080848j:plain

データベースのデータが取得でき、無事表示できました。

f:id:ts0818:20170910080844j:plain


 
⇩  高度なSpring Data JPAの利用については下記サイトへ

Spring Data JPAのEntityの相互参照とその注意点 - Qiita

 

Springの仕組みをいろいろ覚えていかねばですね...覚えること多すぎますね(涙)