[初心者のJava]とりあえず何か作ってみる

ということで、開発環境の準備ができたので簡単でデータベースも使うようなアプリケーションということで金銭出納帳を作ってみようかと思います。

とりあえず以前に手を付けてみたフットボールの勝敗表をSpring Bootで作ってみようかと思います。

プロジェクトを作成する

まずはプロジェクトを作成します。

Eclipseの「ファイル(F)」メニューから「新規(N)」サブメニューを選択し、「Sprintスターター・プロジェクト (Spring Initializr)」を選択します。

「新規Sprintスターター・プロジェクト (Spring Initializr)」画面が表示されますので、「名前」、「グループ」、「説明」、「パッケージ」を設定して「次へ(N)」をクリックします。

成果物は自動的に設定されるので、そのまま変更しなくてもいいと思います。

「新規Springスターター・プロジェクト依存関係」画面が表示されるので「開発者ツール」から「Spring Boot DevTools」と「Lombok」、「SQL」から「Spring Data JPA」と「MySQL Driver」、「テンプレート・エンジン」から「Thymeleaf」、「Web」から「Spring Web」の合計6点にチェックマークを入れます。

一度選択された項目は上の図のようにリスト表示されるようになりますのでリストが表示されている場合にはそちらでチェックマークを付けても構いません。

「完了(F)」をクリックするとプロジェクトが作成され、プロジェクトの初期化が行われます。

初期化が行われている間は上の図のように画面右下に進行表示がされますので、それが消えるまでしばらく待ってください。

データベースアクセスの準備

まず、データベースアクセスの準備としてapplication.propertiesファイルを編集します。

プロジェクトの「src/main/resources」を展開すると「application.properties」ファイルができているので、それをダブルクリックしてエディタに開きます。

以下の4行を入力します。

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/standings
spring.datasource.username=sampleUser

spring.datasource.password=SU_pass

「spring.datasource.driver-class-name」は使用するデータベースのJDBCコネクタのクラス名で、今回は前回と同じMySQLを使用するので「com.mysql.cj.jdbc.Driver」を指定しています。

「spring.datasource.url」はデータベースへのアクセス先で、これも前回作成したstandingsデータベースを使用するので「jdbc:mysql://localhost:3306/standings」を指定しています。

「spring.datasource.username」および「spring.datasource.password」はそれぞれデータベースアクセス用のユーザ名とパスワードで、これらも前回と同じものを指定しています。

エンティティの作成

Spring Data JPAを使用してデータベースアクセスを行おうと考えていますので、まずエンティティクラスを作成します。

エンティティクラスはデータベースレコードを反映したクラスで、Spring Data JPAではデータベースとのデータのやり取りをエンティティクラスを通して行います。

まず、Eclipseの「ファイル(F)」メニューから「新規(N)」サブメニューより「クラス」を選択します。

「新規Javaクラス」画面が表示されますので、「名前」にクラス名を設定して「完了(F)」をクリックします。

Spring Data JPAの特長というか、Springフレームワーク共通の特長でもあるのですが、構成要素とのなるクラスは基本的に何のクラスも継承しない素のJavaクラスとして定義し、その代わりにアノテーションで各クラスの役割をフレームワークに知らせる構成となっています。

それではエンティティクラスを作っていきます。

まず、データベースレコードに対応したフィールドを作っていきます。

package com.example.demo;
import java.time.LocalDate;
public class Match {

  private Integer id;

  private int section;

  private LocalDate date;

  private String home;

  private String away;

  private int goalsFor;

  private int goalsAgainst;

}

データベース上はすべてのカラムにNOT NULLを指定しているので、INT型のカラムにはJavaでもint型のフィールドを割り当てていますが、主キーのidだけはInteger型としています。

これはSpring Data JPAの更新処理が主キーの一致するレコードが存在する場合は更新、しない場合は追加になる仕様となっていて、主キーであるidをint型にすると新規追加の際に-1などのマジックナンバーをidに指定しなければいけなくなるのが気持ち悪いので、新規追加の際にnullを指定できるInteger型をidに割り当てています。

次にアノテーションを設定してきます。

クラスにはエンティティを示す「@Entity」とレコードが記録されているテーブルを示す「@Table(name="matches")」の2個のアノテーションを設定します。

主キーであるidには主キーを示す「@Id」と自動採番されることを示す「@GeneratedValue(strategy=GenerationType.IDENTITY)」を設定します。

その他のフィールドについてはカラム名とフィールド名が一致していれば特に何も設定する必要はありませんが、カラム名とフィールド名が一致していない場合には「@Column(name="goals_for")」のようにアノテーションを設定する必要があります (実際には下線つなぎのカラム名は大文字で区切ったフィールド名に自動的に変換されるので、これも必要はありません。)

ところで、各フィールドはprivateで定義されているので、このままではJavaプログラムからアクセスすることができません。このため、各フィールドにアクセスするためのセッター・ゲッターを作成します。

Lombokを使用するとセッター・ゲッターがそれぞれ「@Setter」、「@Getter」のアノテーションを付けるだけで自動生成されるので、各フィールドにこれらのアノテーションを付けておきます。

以上でエンティティは完成になります。

できあがったエンティティクラスは以下のとおりです。

package com.example.demo;
import java.time.LocalDate;
import javax.persistence.Entity;

import javax.persistence.GeneratedValue;

import javax.persistence.GenerationType;

import javax.persistence.Id;

import javax.persistence.Table;

import lombok.Getter;

import lombok.Setter;

@Entity

@Table(name="matches")

public class Match {

@Setter @Getter

@Id @GeneratedValue(strategy=GenerationType.IDENTITY)

private Integer id;

@Setter @Getter

private int section;

@Setter @Getter

private LocalDate date;

@Setter @Getter

private String home;

@Setter @Getter

private String away;

@Setter @Getter

private int goalsFor;

@Setter @Getter

private int goalsAgainst;

}

レポジトリの作成

次にデータベースにアクセスするためのレポジトリを作成します。

レポジトリはJpaRepositoryを継承するインタフェースとして定義します。

Eclipseの「ファイル(F)」メニューから「新規(N)」サブメニューより「インターフェース」を選択します。

「新規Javaインターフェース」画面が表示されますので、「名前」にインターフェース名を設定して「追加(A)」ボタンで「拡張インターフェースの選択」画面を表示して「JpaRepository」を入力した後、表示された候補をクリックして「追加(A)」ボタンをクリックしてください。

上図のように拡張インターフェースが表示されますので「完了(F)」をクリックします。

拡張インターフェースを指定しなくても、ソースコードに自分で書けばいいので、名前を指定して完了をクリックしても構いません。

まず、JpaRepositoryの型引数がTとIDになっているので、それぞれをエンティティ型とエンティティの主キー型に書き換えます。

今回の例では「T」に「Match」、「ID」に「Integer」を設定します。

次にインタフェースに「@Repository」アノテーションを付けます。

以上で基本的なデータベースアクセス (全レコード検索、主キーによるレコード検索、レコードの追加・更新) が可能になります。

できあがったレポジトリは以下のようになります。

/**
*
*/

package com.example.demo;

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

import org.springframework.stereotype.Repository;

/**

* @author bewise

*

*/

@Repository

public interface MatchRepository extends JpaRepository<Match, Integer> {

}

ページを作成する

続いて試合一覧を表示するページをThymeleafテンプレートを使用して作っていきます。

ThymeleafテンプレートはHTMLファイルに所定の属性を付けていくだけで自動的に様々な値を埋め込めるようにするテンプレートで、Spring Bootと協調して動作するように作られています。

パッケージエクスプローラで「src/main/resources」の下の「templates」を選択してから「ファイル(F)」メニューから「新規(N)」サブメニューより「その他(O)」を選択します。

「ウィザードを選択」画面が表示されますので、「Web」を展開して「HTMLファイル」を選択して「次へ(N)」をクリックしてください。

「新規HTMLファイル」画面が表示されますので、「ファイル名(M)」にファイル名を入力して「完了(F)」をクリックしてください。

HTMLファイルがエディタに表示されたら、まずThymeleafテンプレートを使用する宣言としてThymeleafの名前空間宣言「xmlns:th="http://www.thymeleaf.org」をhtmlタグに追加します。

続いてtitle要素にタイトル、body要素内に表題の<h1>要素と水平線<hr>を入れた後、テーブルを作成します。

テーブルの1行目は各列の見出しを普通に書いていきます。

2行目は以下のように記述します。

<tr th:each="match: ${matches}">
  <td th:text="${match.section}"></td>
  <td th:text="${match.date}"></td>

  <td th:text="${match.home}"></td>

  <td th:text="${match.goalsFor} + ' - ' + ${match.goalsAgainst}"></td>

  <td th:text="${match.away}"></td>

</tr>

trタグにつけられている「th:each="match: ${matches}"」属性は繰り返しをしているもので、matchesとして渡されたリスト・配列から1要素ずつ取り出してmatchに設定して要素を繰り返すというもので、matchesリストの要素数だけtr要素が繰り返されます。

tdタグにつけられている「th:text="${match.section}"」などはそれぞれmatchに設定されたオブジェクトのsectionプロパティなど各プロパティを取り出して要素のテキストとして設定することを指示しています。

これによりJavaオブジェクトのデータをHTMLに埋め込むことができます。

作成したHTMLファイルを以下に示します。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>

  <meta charset="UTF-8">

  <title>Match Results</title>

</head>

<body>

  <h1>試合一覧</h1>

  <hr>

  <table border="1">

    <tr>

      <th>節</th>

      <th>日付</th>

      <th>ホーム</th>

      <th>得点</th>

      <th>アウェイ</th>

    </tr>

    <tr th:each="match: ${matches}">

      <td th:text="${match.section}"></td>

      <td th:text="${match.date}"></td>

      <td th:text="${match.home}"></td>

      <td th:text="${match.goalsFor} + ' - ' + ${match.goalsAgainst}"></td>

      <td th:text="${match.away}"></td>

    </tr>

  </table>

</body>

</html>

コントローラの作成

最後にWebからの入力を受け取って画面を表示するコントローラを作ります。

と言っても今回は単に表示するだけなので非常に簡単です。

まず、クラスを作ります。

クラスにはコントローラを示す「@Controller」アノテーションを付けます。

次にWebからの入力を処理するメソッドを作成します。

メソッドにはいくつかの書き方がありますが、今回はModel型の引数を受け取ってString型を返すmatchesメソッドとして作成します。

Model型の引数にはThymeleafテンプレートに引き渡すデータを設定し、戻り値としてテンプレート名を返すだけでテンプレートに従った表示が可能となります。

メソッドとWeb入力を紐づけるにはメソッドに「@GetMapping(value="/matches")」アノテーションを設定します。これにより/matchesへのgetアクセスがこのメソッドへの呼び出しとして処理されるようになります。

次にレポジトリとの接続を行います。

レポジトリとの接続はレポジトリ型のフィールドを作成し、「@Autowired」アノテーションを付けます。

これによりレポジトリインタフェースを実装したクラスが自動的に生成されて、フィールドに代入されます。

レポジトリからの全レコード取得には自動生成されたfindAll()メソッドを使用します。

取得したレコードをModelのaddAttributeで「matches」という名前と紐づけます。

最後にHTMLファイル名から拡張子を除いたテンプレート名「matches」を戻り値として返すことで表示ができるようになります。

できあがったコントローラは以下のとおりです。

package com.example.demo;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;

import org.springframework.ui.Model;

import org.springframework.web.bind.annotation.GetMapping;

@Controller

public class MatchController {

  @Autowired

  MatchRepository matchRepository;

  @GetMapping(value="/matches")

  public String matches(Model model) {

    List<Match> list = matchRepository.findAll();

    model.addAttribute("matches", list);

    return "matches";

  }

}

プロジェクトの右クリックメニューから「実行(R)」の「9 Spring Bootアプリケーション」を選択するとWebアプリケーションが起動します。

今回は@GetMappingアノテーションでvalue="/matches"を指定したので、「http://localhost:8080/matches」にブラウザからアクセスすると試合一覧が表示されます。

以上、あまりにあっけないほど簡単にWebアプリケーションが作れました。

次回は入力系を扱いたいと思います。


0コメント

  • 1000 / 1000