一覧画面にDBからデータを取得し、その値を表示するということをゴールに行っていきます。
今後DBの中身を確認したりデータ作成したりは「TablePlus」というツールを使用して実施していきます。
使い方や設定方法以下を参考にしてみてください。
テーブル構成
テーブル構成は以下の3テーブルとします。
diary:日記のデータを格納
category_code:検索条件の分類を管理
users:ログインユーザを管理
テーブル名 | 項目名 | 型 | PK | NULL |
---|---|---|---|---|
diary | id | serial | ○ | × |
category | varchar(2) | × | × | |
content | text | × | ○ | |
date | date | × | × | |
update_datetime | timestamp | × | ○ |
テーブル名 | 項目名 | 型 | PK | NULL |
---|---|---|---|---|
category_code | id | serial | ○ | × |
group_cd | varchar(2) | × | ○ | |
cd | varchar(2) | × | ○ | |
name | varchar(20) | × | ○ |
テーブル名 | 項目名 | 型 | PK | NULL |
---|---|---|---|---|
users | id | serial | ○ | × |
user_id | varchar(10) | × | × | |
password | varchar(60) | × | × | |
username | varchar(50) | × | ○ |
※PostgreSQLのデータ型は以下を参考にしてください
https://www.postgresql.jp/document/9.3/html/datatype.html
テーブル作成
DBに接続してCREATE文を実行するのでいいのですが、
Spring Bootにて設定することができますので、そちらで実施していきます。
「src/main/resources」配下に「schema.sql」を作成します。
作成したファイルに以下を記述します。
CREATE TABLE IF NOT EXISTS diary(
id serial,
category varchar(2),
title varchar(50) NOT NULL,
content text,
date date NOT NULL,
update_datetime timestamp,
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS category_code(
id serial,
group_cd varchar(2),
cd varchar(2),
name varchar(20),
PRIMARY KEY(id)
);
CREATE TABLE IF NOT EXISTS users(
id serial,
user_id varchar(10) NOT NULL,
password varchar(60) NOT NULL,
username varchar(50),
PRIMARY KEY(id)
)
次に「src/main/resources」配下に存在する「application.properties」の末尾に以下1行追加します。
spring.datasource.initialization-mode=always
これを記述すると毎回以下SQLファイルが存在する場合、起動時に毎回実行されます。
・schema.sql(テーブル追加等を記述してデータ定義をする)
・data.sql(データ追加等を記述してデータ操作をする)
今回は「schema.sql」が対象です。
毎回実行されてしまうため、SQL文は一工夫が必要です。
CREATE文に「IF NOT EXISTS」を記載しています。
これを記述することで存在していなければ作成となります。
これがないと2回目以降実行する場合「既に存在しています」とエラーになってしまいます。
実際にアプリケーションを実行してみましょう。
実行できたらDBを確認してみてください。作成されているはずです。
コンソール上から確認する方法
データベース、ユーザーを指定して対話モードに入ります。
./psql -d diary -U appuser
接続後以下コマンドを実行すると表示されます。
\dt;
DAOパターン
DBとの接続はDAOパターンというもので実施していきます。
DAOパターンとはビジネスロジックとデータアクセスの処理を分けて記載することです。
それぞれの独立性を高めることで、修正や拡張する際にメンテナンスしやすくなります。
DAO作成
Entityクラス作成
DBのデータ格納用クラス、Entityクラスを作成していきます。
第3章でコントローラーを作成したようにentityパッケージを作成し、「Diary.java」を作成します。
取得した日記一覧のデータを格納します。
「Diary.java」に以下を記載します。それぞれの値にsetter、getterを用意しています。
package diary.entity;
import java.sql.Timestamp;
public class Diary {
private int id;
private String category;
private String title;
private String content;
private String date;
private Timestamp update_datetime;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public Timestamp getUpdate_datetime() {
return update_datetime;
}
public void setUpdate_datetime(Timestamp update_datetime) {
this.update_datetime = update_datetime;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
repositoryクラス作成
データベースにアクセスするクラスを作成していきます。
repositoryパッケージを作成します。
今後の拡張性やテストのしやすさを考慮して、インターフェースを作成します。
repositoryパッケージ上で右区クリックし、「New」→「Interface」を選択します。
「Name」を「IDiaryDao」としFinishを選択します。
作成したインターフェース以下を記載します。
findListメソッドを作成し、これを使用してデータを取得できるようにします
package diary.repository;
import java.util.List;
import diary.entity.Diary;
public interface IDiaryDao {
// 登録されている日記を取得
List<Diary> findList();
}
インターフェースを作成したので実際の実装クラスを作成していきます。
Nameを「DiaryDao」とします。
Interfacesをしているすると自動で継承のコードを記載してくれますので、「Add」を選択して、
先ほど作成したインターフェースを指定します。
作成したクラスに以下を記載します。
package diary.repository;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import diary.entity.Diary;
@Repository
public class DiaryDao implements IDiaryDao {
private final NamedParameterJdbcTemplate jdbcTemplate;
@Autowired
public DiaryDao(NamedParameterJdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public List<Diary> findList() {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("SELECT d.id, d.category, d.title, d.content, TO_CHAR(d.date, 'YYYY/MM/DD') AS date, d.update_datetime, c.name "
+ "FROM diary AS d INNER JOIN category_code AS c ON d.category = c.cd "
+ "WHERE c.group_cd = '01'");
String sql = sqlBuilder.toString();
// パラメータ設定用Map
Map<String, String> param = new HashMap<>();
//タスク一覧をMapのListで取得
List<Map<String, Object>> resultList = jdbcTemplate.queryForList(sql, param);
//return用の空のListを用意
List<Diary> list = new ArrayList<Diary>();
//データをDiaryにまとめる
for(Map<String, Object> result : resultList) {
Diary diary = new Diary();
diary.setId((int)result.get("id"));
diary.setCategory((String)result.get("category"));
diary.setTitle((String)result.get("title"));
diary.setContent((String)result.get("content"));
diary.setDate((String)result.get("date"));
diary.setUpdate_datetime((Timestamp)result.get("update_datetime"));
diary.setName((String)result.get("name"));
list.add(diary);
}
return list;
}
}
ビジネスロジック部分であるサービスクラスを作成します。
repositoryパッケージを作成し、「DiaryService.java」を作成します。
その中に以下を記載します。
package diary.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import diary.repository.IDiaryDao;
import diary.entity.Diary;
@Service
@Transactional
public class DiaryService {
private final IDiaryDao dao;
@Autowired
public DiaryService(IDiaryDao dao) {
this.dao = dao;
}
public List<Diary> findList() {
return dao.findList();
}
}
ポイント
今回のポイントのおさらいです。
・Springには起動時に自動で実行されるsqlファイルがある
・DAOパターンを利用してデータ取得
・「@Autowired」を使用して依存性を注入
次回は実際に画面の検索条件を元に取得したデータを画面に表示していきます。