LoginSignup
0
0

More than 3 years have passed since last update.

ゼロから始めるSpring Boot その3

Posted at

目標

複数回に分けて実施予定です。
また、以降の記事ではエスケープのため、各項目の@を全角にしています。(コード内は半角なのでご安心ください)
(今まで@とすることでエスケープさせていましたが、見づらい気がしたので...)

  1. SpringBootとは何かをざっくり知る
  2. 環境構築&Hello World!を表示させる
  3. パラメータやオブジェクトの受け渡しをする
  4. 他の機能にも触れてみる ←今回やること

他の機能・・・ちょっとフワっとしてますね。改めて具体的に書きます。

目標(他の機能について)

  1.  DBを操作してみよう(JPA編) ←今回やること
  2.  DBを操作してみよう(MySQL編)
  3.  バリデーション(入力チェック)を導入しよう
  4.  プロパティファイルを読み込もう
  5.  actuatorに触れてみよう(おまけ)
  6.  自作のタグプレフィックスを作ろう(おまけ)

DBを操作してみよう(JPA編)

プロジェクトは前回のものを使いまわします。
作り直してもいいのですが、プロジェクトの作成後にmavenの依存関係を追加するという工程を入れたいと思ったためです。

依存関係の追加

今回はDB操作ということでH2databaseSpring Data JPAを追加します。

  • H2database
    javaのメモリ上で展開することのできるデータベースです。これによりSQL ServerMySQLといったソフトウェアを用意することなく、サクッとデータベースの機能を使うことができます。
  • Spring Data JPA
    javaでO/Rマッピングを行うための機能です。ただ、JPA(Java Persistence API)はこの機能の概念であり、実装はHibernateと呼ばれるライブラリが担っています。
    O/Rマッピングって?
    正式名称はObject-Relational Mappingで、プログラミング言語とデータベースを繋ぐ仕組みのことです。これを利用することで、直感的に書いたソースコードでSQLの操作が可能になります。javaの場合だとJPAのほかにMybatis等のフレームワークがあります。

依存関係を後から追加する方法を幾つか紹介します。
1以外は見なくても特に影響ありません。



1.pom.xmlにコピペ
pom.xmlに以下のコードをコピペします。
pom.xml
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

終わり!これが一番手っ取り早いかもしれませんね。
こういったテンプレートコードはググったり、Mavenのセントラルリポジトリから持ってきます。
Maven リポジトリ検索


しれっと出てきた<scope>って何?

依存関係を追加するタイミングを指定するオプションになります。
自分もruntimetestぐらいしか知らないので、全て載っているサイトを引用させてもらいます。
名称 機能
compile scope の指定を省略した場合のデフォルト値です。全ての状況でクラスパスに追加されます。
provided ライブラリが JDK やコンテナによって提供される場合に指定します。コンパイル時のみクラスパスに追加されます。
runtime 実行時のみに必要な場合に指定します。テストの実行および通常の実行のときにクラスパスに追加されます。
test テストのときのみ必要な場合に指定します。テストのコンパイルと実行のときにクラスパスに追加されます。
system 明示的にクラスパスに追加する場合に指定します。このスコープのライブラリは常に有効であるとみなされ、リポジトリの検索は行われません。

引用元:TECHSCORE 依存性の指定とスコープ




2.Mavenの機能で追加
プロジェクト上、もしくはpom.xml上で右クリック>Maven>依存関係の追加の順にクリック。

グループId=com.h2database
アーティファクトId=h2
スコープ=runtime
を指定してOKをクリック。
※ スコープって何?については1.pom.xmlにコピペを参照してください。

もう一回この画面を開いて
グループId=org.springframework.boot
アーティファクトId=spring-boot-starter-data-jpa
スコープ=compile(おそらくデフォルトで選択済み)
を指定してOKをクリック。

終わり!ぶっちゃけ<dependency>とかのタグを自動で記述してくれるぐらいのメリットしかありません。




3.Mavenの機能で追加(検索利用)
この方法は上手くいかない場合、数分~数十分かかる可能性があります。そのためあまりお勧めはしません。

プロジェクト上、もしくはpom.xml上で右クリック>Maven>依存関係の追加の順にクリック。

グループID、アーティファクトID、または・・・にh2dを入力
検索結果に表示されたcom.h2databaseを選択※1
スコープはruntimeを選択※2
最後にOKをクリックすると追加されます。
※1 何も表示されない場合はこちら
※2 スコープって何?については1.pom.xmlにコピペを参照してください。

もう一度画面を開いて、
グループID、アーティファクトID、または・・・にdata-jpaを入力
検索結果に表示されたspring-boot-data-jpaを選択
スコープはcomplieのまま(デフォルトで選択状態のはず)
最後にOKをクリックすると追加されます。

終わり!
2.Mavenの機能で追加にないメリットとしてはアーティファクトIDをフルで覚える必要がないぐらいです。
また、出来た方は下の何も表示されない場合は飛ばしてください。

何も表示されない場合

原因は色々あるので特定するのは難しいです。
検索欄に3文字以上入力しないと表示されないのは仕様っぽいですが、以下の画像のように:warning:インデックスのダウンロードが・・・と出ているとたまに機能しなくなります。この場合、今から説明する方法で半数の人は直るかと思います。

ウィンドウ>設定>Mavenの順にクリック。
起動時にリポジトリー・インデックス更新をダウンロードをチェックして適用して閉じるをクリック。

ファイル>再開の順にクリックしてSTSを再起動します(普通に×閉じ再起動でも大丈夫です)。そのあと、STSの右下にインデックスの更新中が表示されていればOKです。(完了には数分~数十分かかります)

これが完了すると検索できるようになるかもしれません。



pom.xmlに追加した依存関係がプロジェクトに取り込めていない時もあるのでプロジェクトを更新します。Maven>プロジェクトの更新の順にクリック。

プロジェクトdemoにチェックし、OKをクリック。

更新完了です!


テーブル用クラスの作成

依存関係の追加が終わったら、まず初めにテーブル用クラスを作成しましょう。
com.example.demo内にUserEntityを作成し、以下のコードを書きます。

UserEntity.java
package com.example.demo;

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

@Entity
@Table(name="user")
public class UserEntity {
    @Id
    @Column
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;
    @Column
    private String name;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

アノテーション祭りですね。順に解説します。

  • @Entity
    記述したクラスをエンティティクラス(DBの機能を持ったクラス)として認識させます。
  • @Table
    name : テーブル名を設定します。
  • @Id
    記述したプロパティを主キー(レコードを一意に特定するためのカラム)として認識させます。
  • @Column
    記述したプロパティをカラムとして認識させます。
    name : カラム名を設定します。
    length : カラム長を設定します。
    nullable : NULLを許容するか設定します。
記述例
@Column(name="name",length=10,nullable=false)
private String name;
  • @GeneratedValue
    strategy : 主キーの採番方法を指定します。GenerationType.AUTOの場合、利用するDBに合わせて最適な自動採番(オブジェクトが生成されるごとに1,2,3...と増えていく)が行われるようになります。

リポジトリの作成

続いてUserRepositoryという名前でインターフェースを作成し、以下のコードを追加してください。

UserRepository.java
package com.example.demo;

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

public interface UserRepository extends JpaRepository<UserEntity, Long> {
    public UserEntity findById(int id);
}
  • JpaRepository
    依存関係の追加で触れたJPAの機能を使うために記述します。総称型となっており、<使用するエンティティクラス, Long>を指定します。
  • JpaRepository#findById
    SQL文の代わりを果たすメソッドになります。本来インターフェースは実装(継承した具象クラスを作ること)しなければ意味がありませんが、このように命名規則に従ってメソッド名や引数を定義してあげると、JpaRepositoryがそれに応じた機能を自動で作成してくれます。

要はこんなことをやってくれるわけです。
名称未設定ファイル (1).png

他にも沢山の命名規則があるので、気になった方は公式ドキュメントも読んでみてください。
Spring公式ドキュメント 6.3.2.クエリ作成

コントローラの作成

既に作成してあるDemoController.javaを以下のように書き換えます。

DemoController.java
package com.example.demo;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
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;

@Controller
public class DemoController {

    @Autowired
    private UserRepository repository;

    @PostConstruct
    @Transactional
    public void init() {
        UserEntity entity = new UserEntity();
        entity.setName("hatopo");
        repository.saveAndFlush(entity);
    }

    // このメソッドは特に変更なし
    @RequestMapping(value="/",method=RequestMethod.GET)
    public ModelAndView index() {
        ModelAndView mav=new ModelAndView();
        mav.setViewName("/index");
        return mav;
    }

    @GetMapping("/hello")
    public ModelAndView hello(@RequestParam int id,ModelAndView mav) {
        UserEntity entity = repository.findById(id);
        mav.addObject("name",entity.getName());
        mav.setViewName("/hello");
        return mav;
    }
}
  • @Autowired
    これをオブジェクトに付けると、Springが自動でオブジェクトの生成をしてくれるようになります。DI(依存性注入)を行ってくれるとも言います。
    DI(依存性注入)とは?
    一言でいうと依存性を注入することです。
    依存・・・Aクラスが内部でBクラスを利用している時、AはBに依存しているといいます。
    注入・・・外部から与えるという意味です。 すなわち、クラス内で利用する予定の別クラスを外部から渡してあげることです。
  • @PostConstruct
    これを付けたメソッドは、SpringBootの起動直後に一度だけ呼び出されるようになります。
  • @PreDestroy(今回は使用しません)
    PostConstructと対になっているので紹介。こちらはSpringBootの終了直前に一度だけ呼び出されるようになります。
  • @Transactional
    これを付けたメソッドもしくはクラスは、トランザクション処理(エラーが発生したら巻き戻せる機能)を行えるようになります。
    readOnly : DBを読み取り専用にするか指定します。デフォルトはfalseです。
    timeout : タイムアウトの時間を秒数指定できます。
    rollbackFor : デフォルトの巻き戻し対象であるRuntimeExceptionやSQLException以外のエラーも対象にしたい場合に記述します。
記述例
@Transactional(readOnly=true,timeout=100,rollbackFor=IllegalArgumentException.class)
  • @JpaRepository#saveAndFlush
    引数のオブジェクトをメモリ上のDBに反映させます。

ビューの作成

index.htmlhello.htmlの<body>内も書き換えます。

index.html
<body>
<form action="/hello" method="get">
IDを入力してください<input type="text" name="id"><br>
<input type="submit" value="送信">
</form>
</body>
hello.html
<body>
<span th:text="${name}"></span>さん、おはようございます!
</body>

実行

それではhttp://localhost:8080にアクセスします。

入力欄に1を入れて次へ進むと・・・

メモリ上に展開したDBからid検索を行い、一致したレコードのname(hatopo)を表示することができました!

今回、特に入力チェックなどは書いていないため、文字列を入れたり存在しないIDを入れたりするとエラーになるのでご了承ください。

おさらい

  • H2databaseを使ってメモリ上でDBを展開
  • JPAを使ってjavaのコードでSQLを操作
  • @Entity、@Tableでエンティティの定義
  • @Id、@Column、@GeneratedValeでカラムの定義

次回はMySQLを操作していきましょう。お疲れさまでした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0