Springbootでアプリケーションを開発する際、DBのライブラリは何を使っているのでしょうか?
自分の経験上、結構色んな種類のものがあって非常に悩みどころです。
今回は、SQLファイルを使ってSQL文を発行出来るDoma2というDBアクセスフレームワークを使用して、簡単にDBアクセスを実現していきます。
一個、パターンを覚えておくと、DBアクセスを利用する色んな現場で使えますので、是非ともご確認頂きたいと思います。
環境
環境は以下の通り。
- Springboot : 2.2.6
- Doma2 : 2.20.0
- PostgreSQL : 11.7
- Docker : 19.03.8
DBはDockerを使用して、PostgreSQLをインストールします。
フォルダ構成
今回、作成するファイルのフォルダ構成は以下となります。
demo2-sample
|--src
| |--main
| | |--java
| | | |--com
| | | | |--example
| | | | | |--Demo2SampleApplication.java
| | | | | |--controller
| | | | | | |--SampleController.java
| | | | | |--dao
| | | | | | |--SampleDao.java
| | | | | |--entity
| | | | | | |--Sample.java
| | | | | |--service
| | | | | | |--SampleService.java
| | | | | | |--impl
| | | | | | | |--SampleServiceImpl.java
| | |--resources
| | | |--META-INF
| | | | |--com
| | | | | |--example
| | | | | | |--dao
| | | | | | | |--SampleDao
| | | | | | | | |--selectAll.sql
| | | |--application.properties
| |--test
|--build.gradle
|--Dockerfile
|--docker-compose.yml
ファイルの数が多く、フォルダ構成が結構ややこしいですね。
ポイントは、「resources/META-INF」以下のSQLファイルです。Doma2はSQLファイルベースで、DBアクセスします。
利点は以下となります。
- Doma2はSQLをJavaのクラスやアノテーションを組み合わせて構成するのではなく、SQLファイルで構成されている。
- SQLが書ければ、そのまま知識を使うことが出来る。
- SQLがベースなので、複雑なSQLも簡単に実装が出来る
Springbootプロジェクトの作成
Spring Initializrで楽々プロジェクト作成
Springbootのプロジェクトを作成する際は、以下を使用するのが便利です。
あとで、build.gradleを修正するので、こんな感じで、適当に作っちゃって下さい。
build.gradleの修正
build.gradleの修正はとても難しいです。モジュール間の依存関係を考えたりとか、一番頭を悩ますポイントではないでしょうか?
多分、ここが一番ハマる(自分もハマった)ので、注意深く作業して下さい。
Doma2を使う場合は、以下のようにbuild.gradleを修正する。
plugins {
id 'org.springframework.boot' version '2.2.6.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
// テンポラリディレクトリのパスを定義する
ext.domaResourcesDir = "${buildDir}/tmp/doma-resources"
// domaが注釈処理で参照するリソースをテンポラリディレクトリに抽出
task extractDomaResources(type: Copy, dependsOn: processResources) {
from processResources.destinationDir
include 'doma.compile.config'
include 'META-INF/**/*.sql'
include 'META-INF/**/*.script'
into domaResourcesDir
}
// テンポラリディレクトリ内のリソースをcompileJavaタスクの出力先ディレクトリにコピーする
task copyDomaResources(type: Copy, dependsOn: extractDomaResources) {
from domaResourcesDir
into compileJava.destinationDir
}
repositories {
mavenCentral()
}
compileJava {
// 上述のタスクに依存させる
dependsOn copyDomaResources
// テンポラリディレクトリをcompileJavaタスクの入力ディレクトリに設定する
inputs.dir domaResourcesDir
options.encoding = 'UTF-8'
}
compileTestJava {
options.encoding = 'UTF-8'
// テストの実行時は注釈処理を無効にする
options.compilerArgs = ['-proc:none']
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'org.postgresql:postgresql'
annotationProcessor 'org.projectlombok:lombok'
implementation "org.seasar.doma.boot:doma-spring-boot-starter:1.1.1"
// domaの注釈処理を実行することを示す
annotationProcessor "org.seasar.doma:doma:2.20.0"
// domaへの依存を示す
implementation "org.seasar.doma:doma:2.20.0"
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
application.propertiesの作成
application.propertiesはこんな感じで、DB接続に関するプロパティを設定します。
以下の設定はPostgreSQLですが、自分の環境に合わせて書き換えて下さい。
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://db:5432/sample_db
spring.datasource.username=postgres
spring.datasource.password=password
正しく書くことが出来れば、DB接続が出来ます。
Dockerを使った環境準備
Dockerを使って、環境準備をしていきます。
Dockerについて分からない場合は、以下から確認下さい。
Dockerfileの修正
Dockerfileは以下のような感じで定義。
FROM openjdk:8
RUN mkdir /api
WORKDIR /api
COPY ./gradlew /api
COPY ./build.gradle /api
COPY ./settings.gradle /api
COPY ./src /api/src
COPY ./gradle /api/gradle
ENTRYPOINT ["sh", "./gradlew", "bootRun"]
Dockerfileの使い方の基礎を学びたい方は以下から、ご確認下さい。
docker-compose.ymlの作成
docker-compose.ymlは以下のような感じで。
サービスとして、以下を定義する。
- PostgreSQLを動かすdb
- REST APIを動かすapi
コード例は以下です。
version: "3"
services:
db:
image: postgres:11-alpine
container_name: db
ports:
- 5433:5432
environment:
POSTGRES_PASSWORD: password
POSTGRES_DB: sample_db
POSTGRES_INITDB_ARGS: "--encoding=UTF-8"
volumes:
- db_data:/var/lib/postgresql/data
api:
build: ./
container_name: api
ports:
- "8080:8080"
environment:
spring.datasource.url: "jdbc:postgresql://db:5432/sample_db"
depends_on:
- db
volumes:
db_data: {}
ここまで出来たら、以下のコマンドを流して、環境構築が完了します。
# Dockerイメージのビルド
$ docker-compose build
# Dockerイメージの起動
$ docker-compose up -d
環境ができたらPostgreSQL上に、以下のようにsampleテーブルを作成して、適当にデータを入れて下さい!
create table public.sample ( id serial not null,
name text not null,
age int not null,
constraint sample_pkey primary key (id) );
ここまででDockerの設定が完了しました。
SpringbootにDoma2処理の実装
では、ここまでで環境設定が出来ましたので、Springbootに実装をしていきましょう。
Daoの作成
Daoには実行するSQLのインターフェースを作成します。ビルドした際に、このインターフェースの実装クラスができます。
もし、上記で記載したbuild.gradleの設定が間違えていると、implクラスが正常に出力されませんので、ご注意下さい。
package com.example.dao;
import java.util.List;
import org.seasar.doma.Dao;
import org.seasar.doma.Select;
import org.seasar.doma.boot.ConfigAutowireable;
import com.example.entity.Sample;
@ConfigAutowireable
@Dao
public interface SampleDao {
@Select
List<Sample> selectAll();
}
SQLファイルの作成
Doma2が発行するSQLファイルを作成する必要があるため、作成する。
ポイントは以下の2点!!
- SQLファイルの配置場所で「resources/META-INF」以下にソースコードのDaoと同じパッケージになるように配置する。
- ファイル名はDaoで定義したメソッド名と同じ名前になるようにする。
抜粋すると、こんな感じ。
demo2-sample
|--src
| |--main
| | |--java
| | | |--com
| | | | |--example
| | | | | |--dao
| | | | | | |--SampleDao.java
| | |--resources
| | | |--META-INF
| | | | |--com
| | | | | |--example
| | | | | | |--dao
| | | | | | | |--SampleDao
| | | | | | | | |--selectAll.sql
設定が間違っていると、コンパイルエラーになります。
エンティティの実装
エンティティを実装します。
例なので、すごく簡単な構造です。アノテーションの設定を忘れないようご注意下さい。
package com.example.entity;
import java.io.Serializable;
import org.seasar.doma.Column;
import org.seasar.doma.Entity;
import org.seasar.doma.GeneratedValue;
import org.seasar.doma.GenerationType;
import org.seasar.doma.Id;
import org.seasar.doma.Table;
import lombok.Getter;
import lombok.Setter;
@Entity
@Table(name = "sample")
@Getter
@Setter
public class Sample implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "name")
private String name;
@Column(name = "age")
private int age;
}
サービスの実装
こちらもすごく簡単な構造で。
package com.example.service;
import java.util.List;
import com.example.entity.Sample;
public interface SampleService {
public abstract List<Sample> findAll();
}
こちらは実装クラスです。アノテーションの設定忘れにご注意ください。
package com.example.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.example.dao.SampleDao;
import com.example.entity.Sample;
import com.example.service.SampleService;
@Service
public class SampleServiceImpl implements SampleService {
@Autowired
private SampleDao sampleDao;
@Override
public List<Sample> findAll() {
return sampleDao.selectAll();
}
}
コントローラーの実装
REST APIを作成する。
package com.example.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.example.entity.Sample;
import com.example.service.SampleService;
@RestController
@RequestMapping("/api/sample")
public class SampleController {
@Autowired
private SampleService sampleService;
@CrossOrigin
@RequestMapping(value = "/", method = RequestMethod.GET)
public List<Sample> index() {
return sampleService.findAll();
}
}
では、動かしてみよう!
お待たせしました!ここまでで、動かす準備が整いました。
Dockerコンテナを停止している場合は、再度起動コマンドをコマンドプロンプト、またはターミナルから打ち込んで下さい。すると、DBとSpringbootが起動しますので、「http://localhost:8080/api/sample/」にアクセスして下さい。
登録したデータがJSON形式で返ってきたら成功です!
返ってこない場合は、どこか設定が間違えている可能性がありますので、もう一度、記事を見直して見て下さい!
是非とも、このパターンを覚えて色んな現場やプロジェクトで使ってみて下さい!
コメント