こんにちは。じゅんです。
今回は、開発(ローカル)環境でMySQLとSpringBootを連携させる方法についてまとめます。
Spring Bootプロジェクトの作成は以下の記事で詳しく解説しています。
また、これまでの作業内容については以下の記事にまとめています。
MySQL側のセットアップ
まず、HomebrewでMySQLをインストールします。
brewがインストールされていない場合は公式HPを参考にHomeBrewをインストールします。
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
実行結果の最後にHomebrewをPATHに追加するためのコマンドが記述されるので実行します。
versionが確認できればインストール完了です。
% brew --version
Homebrew 4.3.7
brew install mysql
インストールが完了したらMySQLを起動します。
brew services start mysql
MySQLにログインします。
以下のコードはrootユーザーでログインするコマンドです。
mysql -u root
データベースを作成します。
CREATE DATABASE simple_memo;
以下のコマンドで作成できたか確認できます。
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| simple_memo |
+--------------------+
1 rows in set (0.01 sec)
テーブルを作成するデータベースを選択します。
USE simple_memo;
以下のコマンドでデータベースが作成されたか確認できます。
mysql> SELECT DATABASE();
+-------------+
| DATABASE() |
+-------------+
| simple_memo |
+-------------+
1 row in set (0.00 sec)
テーブルを作成します。作成済みのSpringBootに合わせます。
CREATE TABLE memos (
id INT AUTO_INCREMENT PRIMARY KEY, -- メモのID。自動インクリメントされ、一意の値が設定される
content TEXT, -- メモの内容。
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 作成日時。デフォルトで現在のタイムスタンプが設定される
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP -- 更新日時。デフォルトで現在のタイムスタンプが設定され、更新時に自動的に現在のタイムスタンプに更新される
);
以下のコマンドでテーブルが作成できたか確認できます。
mysql> SHOW TABLES;
+-----------------------+
| Tables_in_simple_memo |
+-----------------------+
| memos |
+-----------------------+
1 row in set (0.01 sec)
なお、テーブルの詳細は以下のコマンドで確認できます。
mysql> DESCRIBE memos;
+------------+-----------+------+-----+-------------------+-----------------------------------------------+
| Field | Type | Null | Key | Default | Extra |
+------------+-----------+------+-----+-------------------+-----------------------------------------------+
| id | int | NO | PRI | NULL | auto_increment |
| content | text | YES | | NULL | |
| created_at | timestamp | YES | | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
| updated_at | timestamp | YES | | CURRENT_TIMESTAMP | DEFAULT_GENERATED on update CURRENT_TIMESTAMP |
+------------+-----------+------+-----+-------------------+-----------------------------------------------+
Spring Boot側のセットアップ
Spring BootプロジェクトにMySQLとMyBatisを設定します。
依存関係の追加
MySQLを扱うためにライブラリやフレームワークを使用します。
使用するライブラリやフレームワークは pom.xml
に追記します。
<!-- MySQLコネクタ -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
<scope>runtime</scope>
</dependency>
<!-- MyBatis Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
SpringBoot起動時に factoryBeanObjectType エラーが発生しました。
調べたところMyBatisのバージョンが合っていない可能性があるとのことなのでv3.0.3にしたところ解消しました。
MySQLへの接続情報の設定
MySQLに接続するための接続情報を application.properties に定義します。
spring.datasource.url=jdbc:mysql://localhost:3306/simple_memo?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.url=jdbc:mysql://localhost:3306/simple_memo?useSSL=false&serverTimezone=UTC
データソースのURLを示します。ここでは、MySQLサーバーがローカルホスト(自分のコンピュータ)の3306ポート(デフォルト)で実行されており、データベース名はsimple_memoです。useSSL=falseはSSLを使用しないことを指定し、serverTimezone=UTCはタイムゾーンをUTCに設定します。
spring.datasource.username=root
データベースに接続するためのユーザー名を指定します。ここでは、MySQLのデフォルトの管理者ユーザーである”root”を使用しています。
マッパーファイルは、データベースとアプリケーションの間で行われるSQLクエリとJavaのメソッドをマッピング(対応づけ)するために作成されます。
永続化層の作成
MemoMapperインターフェースを作成します。
MemoMapperインターフェースは永続化層と呼ばれ、データベースと最も近い層のファイルで、SQLクエリを定義します。
package com.example.simplememo.mapper;
import com.example.simplememo.model.Memo;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface MemoMapper {
@Select("SELECT * FROM memos")
List<Memo> findAll();
@Select("SELECT * FROM memos WHERE id = #{id}")
Memo findById(int id);
@Insert("INSERT INTO memos(content, created_at, updated_at) VALUES(#{content}, #{createdAt}, #{updatedAt})")
@Options(useGeneratedKeys = true, keyProperty = "id")
void insert(Memo memo);
@Update("UPDATE memos SET content=#{content}, updated_at=#{updatedAt} WHERE id=#{id}")
void update(Memo memo);
@Delete("DELETE FROM memos WHERE id=#{id}")
void delete(int id);
}
また、このMapperを使うためには @MapperScan
というアノテーションを@SpringBootApplication
が付いたクラスに追加してMyBatisがMapperをスキャンする必要があります。
package com.example.simplememo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.example.simplememo.mapper")
public class SimpleMemoApplication {
public static void main(String[] args) {
SpringApplication.run(SimpleMemoApplication.class, args);
}
}
ビジネスロジック層の作成
Serviceファイルはビジネスロジック層と呼ばれ、永続化層とプレゼンテーション層の間に位置する層です。データの加工などを行います。
package com.example.simplememo.service;
import com.example.simplememo.mapper.MemoMapper;
import com.example.simplememo.model.Memo;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class MemoService {
private final MemoMapper memoMapper;
public MemoService(MemoMapper memoMapper) {
this.memoMapper = memoMapper;
}
public List<Memo> findAll() {
return memoMapper.findAll();
}
public Memo findById(int id) {
return memoMapper.findById(id);
}
public void insert(Memo memo) {
memoMapper.insert(memo);
}
public void update(Memo memo) {
memoMapper.update(memo);
}
public void delete(int id) {
memoMapper.delete(id);
}
}
se
プレゼンテーション層の修正
Controllerファイルはプレゼンテーション層と呼ばれ、ユーザーからのリクエストを受け取り、適切なサービスを呼び出します。
package com.example.simplememo.controller;
import com.example.simplememo.model.Memo;
import com.example.simplememo.service.MemoService;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.List;
@RestController
@RequestMapping("/api/memos")
public class SimpleMemoController {
private final MemoService memoService;
public SimpleMemoController(MemoService memoService) {
this.memoService = memoService;
}
// 全てのMemoレコードを取得するエンドポイント
@GetMapping
public List<Memo> getAllMemos() {
return memoService.findAll();
}
// 新しいMemoレコードを作成するエンドポイント
@PostMapping
public int createMemo(@RequestBody String content) {
// リクエストの内容から新しいMemoオブジェクトを作成し、Serviceに挿入を依頼
Memo newMemo = new Memo(0, content, LocalDateTime.now(), LocalDateTime.now());
memoService.insert(newMemo);
// 作成したMemoのIDを返す
return newMemo.getId();
}
// 指定されたIDのMemoレコードを更新するエンドポイント
@PutMapping("/{id}")
public void updateMemo(@PathVariable int id, @RequestBody String content) {
// 指定されたIDのMemoレコードをServiceから取得し、内容を更新
Memo memoToUpdate = memoService.findById(id);
if (memoToUpdate != null) {
memoToUpdate.setContent(content);
memoToUpdate.setUpdatedAt(LocalDateTime.now());
memoService.update(memoToUpdate);
}
}
// 指定されたIDのMemoレコードを削除するエンドポイント
@DeleteMapping("/{id}")
public void deleteMemo(@PathVariable int id) {
// 指定されたIDのMemoレコードをServiceから削除
memoService.delete(id);
}
}
クラスファイルの修正
データベースのデータを格納するためのクラスファイルを修正します。
Lombokを使ってコードを簡潔にします。
Lombokの@Dataを使うことで、getterとsetterだけでなく引数なしコンストラクタも省略することができます。(引数ありコンストラクタは定義する必要があります。)
package com.example.simplememo.model;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class Memo {
private int id;
private String content;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
public Memo(int id, String content, LocalDateTime createdAt, LocalDateTime updatedAt) {
this.id = id;
this.content = content;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
}
}
以下のコマンドで実行します。
mvn spring-boot:run
動作確認
SpringBootの動作確認をcurlコマンドで行います。
詳細については以下の記事を参考にしてください。
# メモを作成
$ curl -s -X POST -H "Content-Type: application/json" -d 'サンプル0' http://localhost:8080/api/memos
1
# メモ一覧を表示
$ curl -s -X GET http://localhost:8080/api/memos | jq
[
{
"id": 1,
"content": "サンプル0",
"createdAt": "2024-06-07T07:46:36",
"updatedAt": "2024-06-07T07:46:36"
}
]
MySQLが正常に動作しているかをターミナルから確認します。
$ mysql -u root
# mysqlに入る
mysql> USE simple_memo;
Database changed
mysql> select * from memos;
+----+---------------+---------------------+---------------------+
| id | content | created_at | updated_at |
+----+---------------+---------------------+---------------------+
| 1 | サンプル0 | 2024-06-07 07:46:36 | 2024-06-07 07:46:36 |
+----+---------------+---------------------+---------------------+
1 row in set (0.00 sec)
MySQLに書き込みできていることが分かりました。
まとめ
以上が開発環境でSpringBootとMySQLを連携させる方法でした。
MyBatisのバージョンが合っていなかったところに苦戦しましたが、概ねスムーズに進めたと思います。
コメント