プログラミング逆引き辞典

~ 多言語対応のプログラミングレシピ ~

SpringBoot カレンダー作成API

■開発環境

OS:Windows
フレームワーク:Spring Boot
DB:MySQL
O/Rマッパー:MyBatis
ビルドツール:Gradle
 
 


■API概要

付与したパラメーターを元に対象年月のカレンダーをDBに登録するREST API
・第1パラメーター:年
・第2パラメーター:月
 
カレンダーが作成された場合はリターンコード:1
既に該当年月のカレンダーが存在する場合する場合は作成せずにリターンコード:2を返す
 
曜日は番号で登録
・月曜日:1
・火曜日:2
   ・
   ・
・日曜日:7
 
祝日判定はholiday_flagで制御
・祝日:1
・祝日以外:0
 
 


■作成後のイメージ

・Curlコマンドで作成したいカレンダーの年月をパラメーターに設定して実行

curl http://localhost:8080/2020/4 -XPOST

curl http://localhost:8080/2020/5 -XPOST

 
・DBに登録されたカレンダー
[4月のカレンダー]

mysql> select * from tb_calendar where month_nbr = '4';

+----+----------+-----------+---------+----------+--------------+
| id | year_nbr | month_nbr | day_nbr | week_nbr | holiday_flag |
+----+----------+-----------+---------+----------+--------------+
|  1 |     2020 |         4 |       1 |        3 | 0            |
|  2 |     2020 |         4 |       2 |        4 | 0            |
|  3 |     2020 |         4 |       3 |        5 | 0            |
|  4 |     2020 |         4 |       4 |        6 | 0            |
|  5 |     2020 |         4 |       5 |        7 | 0            |
|  6 |     2020 |         4 |       6 |        1 | 0            |
|  7 |     2020 |         4 |       7 |        2 | 0            |
|  8 |     2020 |         4 |       8 |        3 | 0            |
|  9 |     2020 |         4 |       9 |        4 | 0            |
| 10 |     2020 |         4 |      10 |        5 | 0            |
| 11 |     2020 |         4 |      11 |        6 | 0            |
| 12 |     2020 |         4 |      12 |        7 | 0            |
| 13 |     2020 |         4 |      13 |        1 | 0            |
| 14 |     2020 |         4 |      14 |        2 | 0            |
| 15 |     2020 |         4 |      15 |        3 | 0            |
| 16 |     2020 |         4 |      16 |        4 | 0            |
| 17 |     2020 |         4 |      17 |        5 | 0            |
| 18 |     2020 |         4 |      18 |        6 | 0            |
| 19 |     2020 |         4 |      19 |        7 | 0            |
| 20 |     2020 |         4 |      20 |        1 | 0            |
| 21 |     2020 |         4 |      21 |        2 | 0            |
| 22 |     2020 |         4 |      22 |        3 | 0            |
| 23 |     2020 |         4 |      23 |        4 | 0            |
| 24 |     2020 |         4 |      24 |        5 | 0            |
| 25 |     2020 |         4 |      25 |        6 | 0            |
| 26 |     2020 |         4 |      26 |        7 | 0            |
| 27 |     2020 |         4 |      27 |        1 | 0            |
| 28 |     2020 |         4 |      28 |        2 | 0            |
| 29 |     2020 |         4 |      29 |        3 | 1            |
| 30 |     2020 |         4 |      30 |        4 | 0            |
+----+----------+-----------+---------+----------+--------------+

 
[5月のカレンダー]

mysql> select * from tb_calendar where month_nbr = '5';

+----+----------+-----------+---------+----------+--------------+
| id | year_nbr | month_nbr | day_nbr | week_nbr | holiday_flag |
+----+----------+-----------+---------+----------+--------------+
| 31 |     2020 |         5 |       1 |        5 | 0            |
| 32 |     2020 |         5 |       2 |        6 | 0            |
| 33 |     2020 |         5 |       3 |        7 | 0            |
| 34 |     2020 |         5 |       4 |        1 | 1            |
| 35 |     2020 |         5 |       5 |        2 | 1            |
| 36 |     2020 |         5 |       6 |        3 | 1            |
| 37 |     2020 |         5 |       7 |        4 | 0            |
| 38 |     2020 |         5 |       8 |        5 | 0            |
| 39 |     2020 |         5 |       9 |        6 | 0            |
| 40 |     2020 |         5 |      10 |        7 | 0            |
| 41 |     2020 |         5 |      11 |        1 | 0            |
| 42 |     2020 |         5 |      12 |        2 | 0            |
| 43 |     2020 |         5 |      13 |        3 | 0            |
| 44 |     2020 |         5 |      14 |        4 | 0            |
| 45 |     2020 |         5 |      15 |        5 | 0            |
| 46 |     2020 |         5 |      16 |        6 | 0            |
| 47 |     2020 |         5 |      17 |        7 | 0            |
| 48 |     2020 |         5 |      18 |        1 | 0            |
| 49 |     2020 |         5 |      19 |        2 | 0            |
| 50 |     2020 |         5 |      20 |        3 | 0            |
| 51 |     2020 |         5 |      21 |        4 | 0            |
| 52 |     2020 |         5 |      22 |        5 | 0            |
| 53 |     2020 |         5 |      23 |        6 | 0            |
| 54 |     2020 |         5 |      24 |        7 | 0            |
| 55 |     2020 |         5 |      25 |        1 | 0            |
| 56 |     2020 |         5 |      26 |        2 | 0            |
| 57 |     2020 |         5 |      27 |        3 | 0            |
| 58 |     2020 |         5 |      28 |        4 | 0            |
| 59 |     2020 |         5 |      29 |        5 | 0            |
| 60 |     2020 |         5 |      30 |        6 | 0            |
| 61 |     2020 |         5 |      31 |        7 | 0            |
+----+----------+-----------+---------+----------+--------------+

 
 


■事前準備

【プロジェクト作成】

 ・パッケージ:com.example.test_application
 ・プロジェクト名:TestApplication.java
 
 

【テーブル作成】

下記テーブルを作成しておく
 ・tb_calendar
  week_nbr:1~7で月曜日から日曜日を表示
  holiday_flag:1は祝日
 
 ・tb_holiday
 

・tb_calendar
+--------------+------------+------+-----+---------+----------------+
| Field        | Type       | Null | Key | Default | Extra          |
+--------------+------------+------+-----+---------+----------------+
| id           | int(11)    | NO   | PRI | NULL    | auto_increment |
| year_nbr     | int(11)    | YES  |     | NULL    |                |
| month_nbr    | int(11)    | YES  |     | NULL    |                |
| day_nbr      | int(11)    | YES  |     | NULL    |                |
| week_nbr     | int(11)    | YES  |     | NULL    |                |
| holiday_flag | varchar(1) | YES  |     | NULL    |                |
+--------------+------------+------+-----+---------+----------------+

・tb_holiday
+-----------+-------------+------+-----+---------+----------------+
| Field     | Type        | Null | Key | Default | Extra          |
+-----------+-------------+------+-----+---------+----------------+
| id        | int(11)     | NO   | PRI | NULL    | auto_increment |
| year_nbr  | int(11)     | YES  |     | NULL    |                |
| month_nbr | int(11)     | YES  |     | NULL    |                |
| day_nbr   | int(11)     | YES  |     | NULL    |                |
| content   | varchar(50) | YES  |     | NULL    |                |
+-----------+-------------+------+-----+---------+----------------+

 
 

【祝日設定】

tb_holidayに祝日となるレコードをインサート

insert into tb_holiday values (1, 2020, 4, 29, '昭和の日');
insert into tb_holiday values (2, 2020, 5, 4, 'みどりの日');
insert into tb_holiday values (3, 2020, 5, 5, 'こどもの日');
insert into tb_holiday values (4, 2020, 5, 6, '振替休日');

 
 

【MyBatis Generatorでドメインクラス等を作成】

作成するのは下記クラス、ファイル
 ・TbCalendar.java
 ・TbCalendarExample.java
 ・TbHoliday.java
 ・TbHolidayExample.java
 ・TbCalendarMapper.java
 ・TbHolidayMapper.java
 ・TbCalendarMapper.xml
 ・TbHolidayMapper.xml
 
※MyBatis Generatorの使い方は下記参照
MyBatis Generatorの設定方法と実行
 
 

【DB接続設定】

「application.properties」にMySQLの設定を記述
 
※記述方法は下記参照
SpringBoot入門 vol.6:データベースの準備をしよう
 
 


■ディレクトリ構成

事前準備によりアンダーラインが引かれたクラス、ファイルが作成される
後述の「■クラス・ファイルの作成・編集」で赤文字のファイルを作成・編集する
 
├─java
│ └─com
│   └─example
│     │ TestApplication.java
│     │
│     ├─api
│     │   ①TbCalendarController.java
│     │
│     ├─domain
│     │   TbCalendar.java
│     │   TbCalendarExample.java
│     │   TbHoliday.java
│     │   TbHolidayExample.java
│     │
│     ├─mybatis
│     │ └─mapper
│     │     ③TbCalendarMapper.java
│     │     TbHolidayMapper.java
│     │
│     └─service
│         ②TbCalendarService.java

└─resources
  │ application.properties
  │ generationConfig.xml
  │
  └─com
    └─example
      └─mybatis
        └─mapper
            ④TbCalendarMapper.xml
            TbHolidayMapper.xml
 
 


■クラス・ファイルの作成・編集

尚、③④で記述しているバルクインサートの作成方法は下記参照
MyBatis バルクインサート(MySql編)
 
 
①TbCalendarController.javaを作成

package com.example.api;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import com.example.domain.TbCalendar;
import com.example.domain.TbCalendarExample;
import com.example.mybatis.mapper.TbCalendarMapper;
import com.example.service.TbCalendarService;

@RestController
public class TbCalendarController {
    @Autowired
    TbCalendarMapper tbCalendarMapper;

    @Autowired
    TbCalendarExample tbCalendarExample;

    @Autowired
    TbCalendarService tbCalendarService;

    /***
     * REST API
     * バルクインサート
     * @param yearNbr
     * @param monthNbr
     * @return
     */
    @PostMapping("{yearNbr}/{monthNbr}")
    int createCalendar(@PathVariable("yearNbr") Integer yearNbr, @PathVariable("monthNbr") Integer monthNbr) {
        //リターンコード(バルクインサート実行結果 未実行:0 実行:1);
        int returnCd = 0;

        //パラメーターを元に該当のTbCalendarのレコード数を取得
        long recordCount = tbCalendarService.checkExistCalendar(yearNbr, monthNbr);

        //TbCalendarが存在しない場合はその月のレコードを作成
        if (recordCount == 0) {
            //パラメーターの年月からLocalDateインスタンス作成
            LocalDate ld = LocalDate.of(yearNbr, monthNbr, 1);

            //月末日取得
            int endDay = ld.lengthOfMonth();

            List<TbCalendar> calendarList = new ArrayList<>();

            //TbCalendarにインサートするデータのリストを作成
            for (int dayNbr = 1; dayNbr <= endDay; dayNbr++) {
                TbCalendar tbCalendar = new TbCalendar();

                //年をセット
                tbCalendar.setYearNbr(yearNbr);

                //月をセット
                tbCalendar.setMonthNbr(monthNbr);

                //日をセット
                tbCalendar.setDayNbr(dayNbr);

                //曜日番号をセット
                LocalDate localDate = LocalDate.of(yearNbr, monthNbr, dayNbr);
                tbCalendar.setWeekNbr(localDate.getDayOfWeek().getValue());

                //祝日フラグをセット
                boolean holidayFlag = false;
                holidayFlag = tbCalendarService.isHolidayFlag(localDate);

                if (holidayFlag) {
                    //祝日の場合
                    tbCalendar.setHolidayFlag("1");
                } else {
                    //祝日でない場合
                    tbCalendar.setHolidayFlag("0");
                }
                //リストにセット
                calendarList.add(tbCalendar);
            }
            //TbCalendarにバルクインサート
            tbCalendarService.bulkInsert(calendarList);
            returnCd = 1;
        }

        return returnCd;
    }
}

 
 
②TbCalendarService.javaを作成

package com.example.service;

import java.time.LocalDate;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.example.domain.TbCalendar;
import com.example.domain.TbCalendarExample;
import com.example.domain.TbHolidayExample;
import com.example.mybatis.mapper.TbCalendarMapper;
import com.example.mybatis.mapper.TbHolidayMapper;

@Service
@Transactional
public class TbCalendarService {
    @Autowired
    TbCalendarMapper tbCalendarMapper;

    @Autowired
    TbCalendarExample tbCalendarExample;

    @Autowired
    TbHolidayMapper tbHolidayMapper;

    @Autowired
    TbHolidayExample tbHolidayExample;

    /***
     * TbCalendarテーブルのレコード数を取得
     * @param yearNbr
     * @param monthNbr
     * @return recordCount
     */
    public long checkExistCalendar(int yearNbr, int monthNbr) {
        //年月条件を初期化
        tbCalendarExample.clear();

        //年月を条件にセット
        tbCalendarExample.createCriteria()
            .andYearNbrEqualTo(yearNbr)
            .andMonthNbrEqualTo(monthNbr);

        //レコード数を取得
        long recordCount = tbCalendarMapper.countByExample(tbCalendarExample);

        return recordCount;
    }

    /***
     *TbCalendarの祝日判定
     * @param localDate
     * @return holidayFlag (true:祝日 false:祝日以外)
     */
    public boolean isHolidayFlag(LocalDate localDate) {
        //祝日フラグ
        boolean holidayFlag = false;

        //日付条件を初期化
        tbHolidayExample.clear();

        //日付を条件にセット
        tbHolidayExample.createCriteria()
            .andYearNbrEqualTo(localDate.getYear())
            .andMonthNbrEqualTo(localDate.getMonthValue())
            .andDayNbrEqualTo(localDate.getDayOfMonth());

        //tb_holidayにレコード数を取得
        long holidayRecord = tbHolidayMapper.countByExample(tbHolidayExample);

        //レコードが存在する場合は祝日フラグをON
        if (holidayRecord > 0) {
            holidayFlag = true;
        }

        return holidayFlag;
    }

    /***
     * tb_calendarにバルクインサート
     * @param calendarList
     */
    public void bulkInsert(List<TbCalendar> calendarList) {
        tbCalendarMapper.bulkInsert(calendarList);
    }
}

 
 
③TbCalendarMapper.javaを編集

package com.example.mybatis.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import com.example.domain.TbCalendar;
import com.example.domain.TbCalendarExample;

@Mapper
public interface TbCalendarMapper {
    ・
    ・
    /***
     * バルクインサート
     * @param calendarList
     * @return
     */
    int bulkInsert(@Param("calendarList") List<TbCalendar> calendarList);
}

 
 
④TbCalendarMapper.xmlを編集

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mybatis.mapper.TbCalendarMapper">
    <resultMap id="BaseResultMap" type="com.example.domain.TbCalendar">
    ・
    ・
    ・
    <!-- バルクインサート -->
    <insert id="bulkInsert" parameterType="java.util.List">
        insert into tb_calendar
            (year_nbr
            , month_nbr
            , day_nbr
            , week_nbr
            , holiday_flag)
        values
            <foreach collection="calendarList" item="list" separator=",">
                (#{list.yearNbr}
                ,#{list.monthNbr}
                ,#{list.dayNbr}
                ,#{list.weekNbr}
                ,#{list.holidayFlag})
            </foreach>
    </insert>
</mapper>

 
 


■Curlコマンドでカレンダー作成APIを実行

アプリケーションの実行は下記のどちらでも可
 ・Eclipsからアプリケーションを実行

 ・コマンドプロンプトでJarを作成し、アプリケーションを実行
  実行方法 ⇒ Gradle Jarの作成・実行
 
 
アプリケーションを実行した状態でCurlコマンドを入力するとDBに該当月のカレンダーが登録される

curl http://localhost:8080/2020/4 -XPOST

curl http://localhost:8080/2020/5 -XPOST

 
 
※Curlをインストールしていない場合
インストール方法 ⇒ Curl インストール方法