iris

Java Spring Bootで家計簿アプリを作る:環境構築からAPI作成まで


久しぶりに触ると色々忘れかけてたのでメモ+振り返ります.

勉強のため作り始めた家計簿アプリです.

Java Spring Boot を使ってバックエンドを開発し、データベースには MySQL を使用します.

環境構築

Spring Initializr で作成

Spring Initializr https://start.spring.io/ を使って、プロジェクトを作成します

Spring Initializr はビルドツールや開発言語を選択して、プロジェクトの雛形を簡単に生成できるツールです.

今回は、ビルドツールは Maven、言語は Java を選択しました.

Dependencies の設定

使用するライブラリ(依存関係)を追加します.

MySQL を使いたかったため以下を参考に追加してます. https://spring.pleiades.io/guides/gs/accessing-data-mysql

ホットリロードを使いたかったので、以下も追加しています.

これらの依存関係は、Spring Initializr でプロジェクトを生成した後に pom.xml に自動的に追記されます.

Maven では、プロジェクトの依存関係を pom.xml で管理します.

pom は Project Object Model の略らしいです.

依存関係の他にプロジェクトの設定などもこのファイルで行います.

pom.xml を編集した後は、shift + command + I で再ロードができます.

mvnw というファイルも生成されてます.

mvnw は Maven Wrapper と呼ばれ、プロジェクトに必要な Maven のバージョンを自動で管理します.

これにより、ローカルに Maven をインストールしなくてもビルドを実行できるようになります.

以下のコマンドでアプリケーションを起動できます.

./mvnw spring-boot:run 

IntelliJ では @SpringBootApplication アノテーションが付いているクラスの main メソッドを実行することで、アプリケーションを起動することもできます.

データベース接続

Docker について

compose.yaml というファイルも生成されていると思います.

使用する image や接続情報が記載されてます.

ローカル環境において、ポート3306で MySQL を立ち上げることになります.

application.properties の設定

application.properties はアプリケーションの設定ファイルになります.

データベースの設定もここで行います.

Docker で立ち上げたデータベースと接続できるよう設定します.

spring.datasource.url=jdbc:mysql://localhost:3306/ab
spring.datasource.username=app
spring.datasource.password=passwd
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

アプリケーションが起動するたびに、データベースのスキーマを自動的に更新する設定と

spring.jpa.hibernate.ddl-auto=update

実行された SQL をコンソールに表示する設定も追加します.

spring.jpa.show-sql=true

Model 作成

データベースに対応するクラスを作成します.

カラムに対応するフィールドの定義、型、リレーション、getter/setter メソッドを定義します.

Model名は単数にしたかったので、@Tableアノテーションを使いテーブル名は別途指定してます.

@Table(name = "users")
public class User {

User は複数の Categoryを持つため 1対多のリレーションを設定します.

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, fetch = FetchType.LAZY)

Category側の Model には 多対1 のリレーションを指定します.

    @ManyToOne
    @JoinColumn(name = "user_id") // 外部キーのカラム

idフィールドには、@GeneratedValue で AUTO_INCREMENT を設定します.

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

Repository について

Repository はデータベース操作を簡単に行えるようにするためのインターフェースです.

Spring Data JPA は、データベース操作を効率化するフレームワークで、リポジトリパターンを簡単に実装できます.

Spring Data JPA には、クエリメソッドという便利な機能があり、Repository インターフェースにメソッド名を宣言するだけで、その名前に基づいた SQL クエリを自動的に生成してくれる仕組みがあります.

例えば、findByLoginId のようにメソッド名に findBy を使うと、その後のフィールド名(LoginId)に基づいてクエリが生成され、login_id カラムで検索するクエリが自動的に作成されます.

public interface UserRepository extends CrudRepository<User, Long> {
    User findByLoginId(String loginId);
}

少し複雑なクエリを記述したい場合は、@Query アノテーションを使用して、SQL クエリを直接書くことができます.

    @Query("SELECT DATE(e.paymentAt), SUM(e.amount) FROM Expense e WHERE e.member.id = :memberId AND e.paymentAt BETWEEN :startOfMonth AND :endOfMonth GROUP BY DATE(e.paymentAt) ORDER BY DATE(e.paymentAt)")
    List<Object[]> sumExpensesByMemberGroupByDay(Long memberId, LocalDateTime startOfMonth, LocalDateTime endOfMonth);

コントローラー作成

JSON を返すために、@Controller から @RestController に変更します.

ルーティングについて

Spring では @GetMapping や @PostMapping などのアノテーションを使って、HTTPメソッドに対応するリクエストを処理します.

@GetMapping でルートパス / に対して GET リクエストを受け、currentDate というクエリパラメータを取得しています.

@GetMapping(path="/")
public @ResponseBody HashMap<String, Object> getMemberWithExpenses(
        @RequestParam(value = "currentDate", required = false) String currentDateParam
) {
    // リクエストパラメータを受け取って処理する
}

レスポンスについて

@RestController にすることで、メソッドが返す値(この場合は HashMap)が自動的に JSON としてレスポンスとして返されます.

@ResponseBody の記述は必要ありません.

HashMap<String, Object> response = new HashMap<>();
... 

response.put("currentYearMonth", currentYearMonth.toString());
response.put("totalExpenses", totalExpenses);

return response; // JSON として返される

タイトルに家計簿と含めたもののほとんど触れずに終わってしまった…

必要な機能がまだいくつかあるので、個人で進捗管理として GitHub Projects を活用してみています.

クライアント側の実装についてはまだ迷っているところですが、まずは REST API の作成から進めようかと考えています.