Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SpringBoot3+MyBatisによるWebAPI実装入門

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

 SpringBoot3+MyBatisによるWebAPI実装入門

Udemy講座(作成中)で使用するスライド

Avatar for とらのこ

とらのこ

August 12, 2023

Other Decks in Technology

Transcript

  1. 本講座でできるようになること
 本講座では社員情報管理APIの実装を通して以下のことを学ぶことができます。 
 
 ☝ Java17+SpringBoot3(MyBatis)によるWebAPIの実装方法 
 ☝ Docker ComposeにてMySQLを構築する方法

    
 ☝ バックエンド開発に必要な周辺知識(N+1問題やトランザクション) 
 ☝ 様々な開発ツールの使い方 
 ☝ 応用:MyBatisにおける複数データソースの利用方法 
 2
  2. 本講座にて利用する開発ツール
 3 開発ツール
 利用目的
 Intellij IDEA
 コーディングを効率的に行うための統合開発環境 
 Docker Desktop

    for Mac 
 DockerをmacOS環境で実行するためのツール 
 Postman
 簡単にAPIエンドポイントの動作確認を行えるツール 
 DBeaver
 データベースをGUIで確認するためのクライアントツール 

  3. 本講座を受講するにあたっての事前準備
 6 ✅ Homebrewのインストール 
 ✅ JDK17のインストール 
 ✅ IntelliJ

    IDEAのインストール 
 ✅ Postmanのインストール 
 ✅ DBeaverのインストール 
 ✅ Docker Desktop for Macのインストール 
 ✅ SpringBootプロジェクトの作成 
 ✅ GitHubリポジトリの作成 

  4. テーブル定義 EMPLOYEE(社員)
 9 カラム名(物理) 
 カラム名(論理) 
 型
 PK
 NOT

    NULL
 備考
 EMPLOYEE_ID
 社員ID
 VARCHAR(10)
 ✅
 ✅
 
 DEPARTMENT_ID 
 部署ID
 BIGINT
 
 ✅
 0: 無所属
 1: 人事部
 2: 営業部
 3: 企画部
 4: 開発部
 EMPLOYEE_NAME 
 社員名
 VARCHAR(256) 
 
 ✅
 
 GENDER
 性別
 VARCHAR(256) 
 
 ✅
 
 CREATE_AT
 登録日時
 TIMESTAMP
 
 ✅
 DEFAULT CURRENT_TIMESTAMP 
 UPDATE_AT
 更新日時
 TIMESTAMP
 
 ✅
 DEFAULT CURRENT_TIMESTAMP 
 ON UPDATE CURRENT_TIMESTAMP 

  5. テーブル定義 PERSONAL(個人情報)
 10 カラム名(物理) 
 カラム名(論理) 
 型
 PK
 NOT

    NULL
 備考
 EMPLOYEE_ID
 社員ID
 VARCHAR(10)
 ✅
 ✅
 
 BIRTHDAY
 誕生日
 DATE
 
 ✅
 
 TELEPHONE_NUMBER 
 電話番号
 VARCHAR(256) 
 
 ✅
 
 MAIL_ADDRESS 
 メールアドレス
 VARCHAR(256) 
 
 ✅
 
 CREATE_AT
 登録日時
 TIMESTAMP
 
 ✅
 DEFAULT CURRENT_TIMESTAMP 
 UPDATE_AT
 更新日時
 TIMESTAMP
 
 ✅
 DEFAULT CURRENT_TIMESTAMP 
 ON UPDATE CURRENT_TIMESTAMP 

  6. テーブル定義 HISTORY(社員履歴)
 11 カラム名(物理) 
 カラム名(論理) 
 型
 UK
 NOT

    NULL
 備考
 EMPLOYEE_ID
 社員ID
 VARCHAR(10)
 ✅
 ✅
 
 START_DATE
 開始日
 DATE
 ✅
 ✅
 
 DEPARTMENT_ID 
 部署ID
 BIGINT
 ✅
 ✅
 0: 無所属
 1: 人事部
 2: 営業部
 3: 企画部
 4: 開発部
 CONTENT
 履歴内容
 VARCHAR(256) 
 
 ✅
 
 CREATE_AT
 登録日時
 TIMESTAMP
 
 ✅
 DEFAULT CURRENT_TIMESTAMP 
 UPDATE_AT
 更新日時
 TIMESTAMP
 
 ✅
 DEFAULT CURRENT_TIMESTAMP 
 ON UPDATE CURRENT_TIMESTAMP 

  7. 社員情報管理API エンドポイント全体像
 処理内容
 メソッド
 パス
 リクエスト
 レスポンス
 BODY
 STATUS
 BODY(JSON形式)


    社員情報一覧取得
 GET
 /employee/
 なし
 200 OK
 全ての社員情報
 社員情報取得(ID指定) 
 GET
 /employee/:employeeId 
 なし
 200 OK
 社員IDに該当する社員情報 
 404 Not Found
 エラーメッセージ
 社員情報登録
 POST
 /employee/
 社員情報
 201 Created
 登録後の社員情報
 400 Bad Request
 エラーメッセージ
 社員情報更新
 PUT
 /employee/:employeeId 
 社員情報
 200 OK
 更新後の社員情報
 400 Bad Request
 エラーメッセージ
 404 Not Found
 エラーメッセージ
 社員情報削除
 DELETE
 /employee/:employeeId 
 なし
 204 No Content
 なし
 404 Not Found
 エラーメッセージ
 12
  8. H2 Databaseでイメージをつかもう
 いきなりDockerコンテナ内にMySQLを構築するのではなく、まずは構築が簡単なH2 Databaseでやってみま しょう。
 
 ① H2 Databaseが使えるように build.gradle

    の dependencies に下記を追加 
   runtimeOnly 'com.h2database:h2' 
 
 ② schema.sql を作成 
 
 ③ application.properties に下記を設定 
 
 ④ アプリケーションを起動して h2-consoleを確認 -> http://localhost:8080/h2-console/ 
 
 ⑤ data.sql を作成
 15
  9. DockerコンテナにMySQLを構築する - データベースの作成 -
 DockerHubからMySQLのDockerイメージを取得してきて構築します。 
 https://hub.docker.com/ 
 
 ①

    データベーススキーマをDockerコンテナに作る設定をdocker-compose.ymlに定義 
 
 ② docker compose up -d でコンテナを起動 
 
 ③ Docker Desktopを確認してコンテナが作成、起動しているかを確認 
 
 ④ DockerコンテナのMySQLにDBクライアントツールからアクセスしてみる 
 
 ⑤ データの初期化
 
 ⑥ 文字化けの対策
   -> MySQLのカスタム設定ファイルを定義する。 
   -> docker-compose.yml の volume にカスタム設定を定義する。 
 16
  10. 社員情報一覧取得エンドポイントを作成しよう
 処理内容
 メソッド
 パス
 リクエスト
 レスポンス
 BODY
 STATUS
 BODY(JSON形式)
 社員情報一覧取得


    GET
 /employee/
 なし
 200 OK
 全ての社員情報
 社員情報取得(ID指定) 
 GET
 /employee/:employeeId 
 なし
 200 OK
 社員IDに該当する社員情報 
 404 Not Found
 エラーメッセージ
 社員情報登録
 POST
 /employee/
 社員情報
 201 Created
 登録後の社員情報
 400 Bad Request
 エラーメッセージ
 社員情報更新
 PUT
 /employee/:employeeId 
 社員情報
 200 OK
 更新後の社員情報
 400 Bad Request
 エラーメッセージ
 404 Not Found
 エラーメッセージ
 社員情報削除
 DELETE
 /employee/:employeeId 
 なし
 204 No Content
 なし
 404 Not Found
 エラーメッセージ
 19
  11. 社員情報一覧取得エンドポイントを作成しよう
 ・ Hello, World!を返すようにControllerを仮実装しましょう。 
 
 ・ Postmanで http://localhost:8080/employee/ GETメソッドで実行してみましょう。

    
   ※GETメソッドならブラウザでもOK 
 
 ・ Controllerとレスポンスを仮実装しましょう。(詳細の実装はあとから) 
 
 ・ Serviceクラスを仮実装します。 
 
 ・ ControllerでServiceを利用します。 
 
 20
  12. 社員情報一覧取得エンドポイントを作成しよう これがnewでクラスをインスタンス化する最も大きなデメリットです。 
 
 Serviceが依存するクラスやインターフェースが増えると、 
 都度、Serviceを利用しているクラス(Controller)も修正が必要になります。 
 
 このような状態を、互いが密接に結合しているため『密結合』と言い、

    
 プログラムの保守性が低いなど望ましい状態ではありません。 
 
 それではどのようにすれば、密結合でない状態(=疎結合)にすることができるでしょうか? 
 
 そこで、DI(Dependency Injection = 依存の注入) という概念が必要になります。 
 
 DIを理解するためには、 Bean と DIコンテナ という概念も併せて理解する必要があります。 
 
 参照:Appendix - DI 全体像 - 
 25
  13. 26 Appendix - DI 全体像 - 
 Bean
 @Serviceとか@Beanなどが付与 されたクラスをインスタンス化

    (new)したオブジェクト
 DIコンテナ
 Beanを登録したり、DIという行 為を行う入れ物
 DI
 依存関係を解決する行為

  14. 社員情報一覧取得エンドポイントを作成しよう ・ ServiceがDIコンテナにBean登録されるように@Serviceを付与します。 
 
 ・ ControllerでServiceを利用できるようにコンストラクタを設定します。 
   -> Lombokの

    @AllArgsConstructor を指定すれば コンストラクタの定義を省略できます。 
 
 ・ Postmanで動作を確認してみましょう。> 何やらうまくデータ取得できていない? 
 27 Postmanでの取得結果
 テーブル定義(EMPLOYEE) 

  15. 社員情報一覧取得エンドポイントを作成しよう テーブルのカラム名と、データをマッピングしたいオブジェクト内(EmployeeEntity)のフィールド名が違うため、 Mybatisがうまくマッピングできていないようです。 
 
 では、EmployeeEntityのフィールド名にアンダースコアをつけますか? 
 
 Javaのコーディング規約では、アンダースコアを変数名に含めることは推奨されていません。 


    代わりに、キャメルケースの命名規則を使用することが推奨されています。 
 
 そこで、Mybatisにはアンダースコアをキャメルケースにマッピングしてくれる設定があります。 
 application.propertiesに下記の設定を追加して再度Postmanで動作確認してみましょう。 
 
 # mybatis
 mybatis.configuration.map-underscore-to-camel-case =true
 28
  16. 社員情報一覧取得エンドポイントを作成しよう 続いて、Personalデータの取得処理を実装します。 
 
 ① PersonalMapperの実装 
 
 ② PersonalEntityの実装

    
 
 ③ PersonalMapperをService側で利用するように修正 
 
 ④ EmployeeResponseにレスポンスするPersonalデータのフィールド追加 
 29
  17. 社員情報一覧取得エンドポイントを作成しよう ・Personalデータの取得処理を実装します。 
 
 ・Postmanで動作を確認してみましょう。 
 30 一見よさそうに見えますが、ある疑念が生まれてきます。 
 社員が複数人いたらどうなるだろう・・?

    
 
 DBeaverで直接データを追加し、Postmanで確認してみよう。 
 
 すると、ただのデータの羅列で、データが社員単位のツリー構造に なっていないのがわかります。 
 { "employees": [ { "employeeId": "dummy", "departmentId": 1, "employeeName": "ダミー", "gender": "FEMALE", "createAt": "2023-04-30", "updateAt": "2023-04-30", } ], "personal": [ { "employeeId": "dummy", "birthday": "2023-01-01", "telephoneNumber": "00000000000", "telephoneNumber": "[email protected]", "createAt": "2023-04-30", "updateAt": "2023-04-30", } ] }
  18. 社員情報一覧取得エンドポイントを作成しよう データが社員単位のツリー構造になっていないというのはどういうことでしょうか? 
 31 現状
 { "社員基本情報": [ {社員1の基本情報}, {社員2の基本情報},

    ], "社員個人情報": [ {社員1の個人情報}, {社員2の個人情報}, ] } 理想
 { "社員1": [ {社員1の基本情報}, {社員1の個人情報}, ], "社員2": [ {社員2の基本情報}, {社員2の個人情報}, ] } 情報が社員単位の
 ひとかたまりになっていない。 

  19. 社員情報一覧取得エンドポイントを作成しよう
 ・理想形となるようEmployeeResponseのデータ構造を修正しましょう。 
 32 @Builder
 @Data
 @NoArgsConstructor
 @AllArgsConstructor
 public class

    EmployeeResponse {
 // 社員一覧
 private List<EmployeeDto> employeeDtoList;
 }
 @Builder
 @Data
 @NoArgsConstructor
 @AllArgsConstructor
 public class EmployeeDto {
 // 社員基本情報
 EmployeeEntity employee;
 // 社員個人情報
 PersonalEntity personal;
 }
 すると今度はServiceクラスでエラーが出ます。 
 employeeDtoListにはList<EmployeeDto>のオブジェクトが入る必要があります。 
 List<EmployeeDto>のオブジェクトを作成してemployeeDtoListに設定しましょう。 

  20. 社員情報一覧取得エンドポイントを作成しよう (N+1問題とは?)
 N+1問題とは、あるオブジェクトに関連する別のオブジェクトを取得する際、必要以上にクエリを実行してしまうこと で、パフォーマンスに影響を与える問題です。 
 
 今回の例でいうと、
 
 STEP1: EMPLOYEEテーブルから社員基本情報を全件取得する(1回)

    
 STEP2: 取得した社員基本情報の数(N回)だけ、PERSONALテーブルに検索をかける 
 
 では、N+1問題を回避するにはどうすれば良いでしょうか? 
 
 主な方法は2つあります。 
 
 ① EMPLOYEEテーブルとPERSONALテーブルを全件取得しプログラム側でやりくりする。(非推奨) 
 ② SQLでJOIN句を利用することで社員基本情報と社員個人情報を1回で取得できるようにする(推奨) 
 34
  21. 社員情報一覧取得エンドポイントを作成しよう (N+1問題の回避策①) ① EMPLOYEEテーブルとPERSONALテーブルを全件取得しプログラム側でやりくりする。 
 35 最初に各テーブルを全件取得したことで、 
 データベースへの検索回数がN+1回から 


    2回に減りました。
 
 しかし、プログラムが煩雑、かつ多重ループしてい るため、処理速度が遅くなることが考えられます。 
 
 また、保守性も低いです。 
 
 よって、N+1問題の回避策としては、非推奨です。 

  22. 社員情報一覧取得エンドポイントを作成しよう (N+1問題の回避策②) STEP1: XMLでのSQL定義を利用できるようにする。 
 
 XMLの置き場所は、resources配下に、Mapperインターフェースと同階層パッケージを作成して、配置します。 
 
 Mapperインターフェースの置き場所:main/java/com/course/restapi/springboot/mybatis/infrastructure/mapper


    MapperXMLの置き場所:main/resources/com/course/restapi/springboot/mybatis/infrastructure/mapper
 
 そうすることで@MapperアノテーションをつけているMapperインターフェースが、アプリケーション起動時に resources内の同階層のXMLをスキャンして自動で紐付けしてくれます。 
 ※XMLのファイル名は、Mapperインターフェース名と同名にします。 
 
 もしくは、任意のパッケージを作成してMapperXMLを配置し、 
 その任意のパッケージの場所をapplicaiton.properties に記載することでも可能です。 
 
 mybatis.mapper-locations=classpath*:/mapper/*.xml
 
 38
  23. 社員情報一覧取得エンドポイントを作成しよう (N+1問題の回避策②) STEP2: アノテーションで定義していたSQLをXMLに転記する。 -> 動作確認 
 
 <XMLの定義について> 


    - https://mybatis.org/mybatis-3/ja/getting-started.html#mapped-sql-statements-%E3%81%AB%E3%81%A4 %E3%81%84%E3%81%A6 
 - https://mybatis.org/mybatis-3/ja/sqlmap-xml.html#select 
 39
  24. 社員情報一覧取得エンドポイントを作成しよう (N+1問題の回避策②) STEP3: JOIN句を含むSQLに変更します。 
 
 JOIN句を含むSQLをMapperXMLに記述したら、取得した値をどのようにしてEmployeeDtoにマッピングすれば良 いでしょうか?
 
 これまでのマッピングとは異なり、EmployeeDtoはEmployeeEntityやPersonalEntitiyなど別のオブジェクトを持って

    おり(has-one)そのオブジェクト内のフィールドに取得結果をマッピングしたいです。 
 
 <高度なマッピング> 
 https://mybatis.org/mybatis-3/ja/sqlmap-xml.html#%E9%AB%98%E5%BA%A6%E3%81%AA%E7%B5%90%E6%9E%9C% E3%83%9E%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0 
 40 STEP4: Javaコードの修正 -> 動作確認
  25. 社員情報一覧取得エンドポイントを作成しよう ・社員情報一覧取得エンドポイントの実装の最後にHISTORYテーブルの取得をしましょう。 
 
 ① HistoryEntitiyクラスを作成 
 ② EmployeeDtoの修正 


    ③ EmployeeMapper.xmlの修正 
 -> Historyは社員1人に対して複数の履歴が存在します。(has-many) 
 -> どのようにマッピングすればいいでしょうか? 
 -> <collection>を利用します。 
 
 <高度なマッピング> 
 https://mybatis.org/mybatis-3/ja/sqlmap-xml.html#%E9%AB%98%E5%BA%A6%E3%81%AA%E7%B5%90%E6%9E%9C %E3%83%9E%E3%83%83%E3%83%94%E3%83%B3%E3%82%B0 
 41
  26. 社員情報取得(ID指定)エンドポイントを実装しよう
 42 処理内容
 メソッド
 パス
 リクエスト
 レスポンス
 BODY
 STATUS
 BODY(JSON形式)


    社員情報一覧取得
 GET
 /employee/
 なし
 200 OK
 全ての社員情報
 社員情報取得(ID指定) 
 GET
 /employee/:employeeId 
 なし
 200 OK
 社員IDに該当する社員情報 
 404 Not Found
 エラーメッセージ
 社員情報登録
 POST
 /employee/
 社員情報
 201 Created
 登録後の社員情報
 400 Bad Request
 エラーメッセージ
 社員情報更新
 PUT
 /employee/:employeeId 
 社員情報
 200 OK
 更新後の社員情報
 400 Bad Request
 エラーメッセージ
 404 Not Found
 エラーメッセージ
 社員情報削除
 DELETE
 /employee/:employeeId 
 なし
 204 No Content
 なし
 404 Not Found
 エラーメッセージ

  27. 社員情報取得(ID指定)エンドポイントを実装しよう 存在しない社員IDで検索をかけたときは適切なエラーコードとメッセージを返却してあげましょう。 
 エラーコード エラーメッセージ 404 Not Found Employee not

    found with employeeId: {employeeId} EmployeeNotFoundExceptionを発生させてエラーハンドリングしましょう。 
 -> SpringBootの@ExceptionHandlerを利用する。 
 
 参考:
 https://www.educative.io/answers/exception-handling-in-spring-boot 
 
 43
  28. 社員情報登録エンドポイントを実装しよう
 45 処理内容
 メソッド
 パス
 リクエスト
 レスポンス
 BODY
 STATUS
 BODY(JSON形式)


    社員情報一覧取得
 GET
 /employee/
 なし
 200 OK
 全ての社員情報
 社員情報取得(ID指定) 
 GET
 /employee/:employeeId 
 なし
 200 OK
 社員IDに該当する社員情報 
 404 Not Found
 エラーメッセージ
 社員情報登録
 POST
 /employee/
 社員情報
 201 Created
 登録後の社員情報
 400 Bad Request
 エラーメッセージ
 社員情報更新
 PUT
 /employee/:employeeId 
 社員情報
 200 OK
 更新後の社員情報
 400 Bad Request
 エラーメッセージ
 404 Not Found
 エラーメッセージ
 社員情報削除
 DELETE
 /employee/:employeeId 
 なし
 204 No Content
 なし
 404 Not Found
 エラーメッセージ

  29. 社員情報登録エンドポイントを実装しよう
 46 ・ Controllerの実装(Serviceも仮実装)を行う 
 
 ・ リクエストBODYをマッピングするオブジェクトを作成する 
 


    ・ リクエストBODYがきちんとアプリケーションに受け渡しされているかを確認する 
 
 ・ Serviceで、テーブルへのデータ登録のためにリクエストデータをEntityに詰め替える 
 
 ・ 各Mapperインターフェースにinsertメソッドを追加 
 
 ・ 各MapperXMLにINSERT文を追加 
 
 ・ Serviceで、戻り値を設定する 
 
 ・ 動作を確認する

  30. 社員情報登録エンドポイントを実装しよう
 48 ① リクエストBODYの検査(バリデーション)がされていない 
 
 ・バリデーションを行えるように依存関係を追加する。 
 
 ・バリデーションを行うリクエストに

    @Valid を付与する。 
 
 ・フィールドごとに実施すべきバリデーションができるようにする。-> 動作確認 
 
 ・バリデーション時のエラーハンドリングをして、エラー箇所を特定できるようにする。 
 参考: https://spring.pleiades.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/M ethodArgumentNotValidException.html 

  31. 社員情報登録エンドポイントを実装しよう
 ② トランザクション制御がされていない 
 
 トランザクションの実装( @Transactional)をしていきましょう。 
 51 ポイント


    
 ☝ @Transactionalを付与したメソッドを別クラスから呼び出す。 
    -> 同じクラスから呼び出しても機能してくれない。 
 
 ☝ @Transactionalを付与したメソッドは直接呼び出す。 
 
 ☝ @Transactionalを付与するメソッドはpublicである必要がある。 
 
 ☝ 実際の業務ではトランザクションの伝播属性と分離レベルについても意識する。 
 -> 本講座では @Transactional のデフォルトにする 
 

  32. 社員情報更新エンドポイントを実装しよう
 53 処理内容
 メソッド
 パス
 リクエスト
 レスポンス
 BODY
 STATUS
 BODY(JSON形式)


    社員情報一覧取得
 GET
 /employee/
 なし
 200 OK
 全ての社員情報
 社員情報取得(ID指定) 
 GET
 /employee/:employeeId 
 なし
 200 OK
 社員IDに該当する社員情報 
 404 Not Found
 エラーメッセージ
 社員情報登録
 POST
 /employee/
 社員情報
 201 Created
 登録後の社員情報
 400 Bad Request
 エラーメッセージ
 社員情報更新
 PUT
 /employee/:employeeId 
 社員情報
 200 OK
 更新後の社員情報
 400 Bad Request
 エラーメッセージ
 404 Not Found
 エラーメッセージ
 社員情報削除
 DELETE
 /employee/:employeeId 
 なし
 204 No Content
 なし
 404 Not Found
 エラーメッセージ

  33. 社員情報更新エンドポイントを実装しよう
 54 社員履歴(HISTORYテーブル)の更新について 
 
 過去の社員履歴を変更する場合もあるかもしれませんが、どちらかというと、新規の履歴を追加するという意味合 いでの「更新」のほうが多い気がします。 
 
 過去の社員履歴を変更する場合はUPDATE、新規の社員履歴を追加する場合はINSERT文、という風にプログラム

    で制御することもできますが、ちょっと面倒な気がしますね・・ 
 
 そこで、MySQLにおける INSERT ... ON DUPLICATE KEY UPDATE ステートメントを利用します。 
 ※ 通称 Upsert(Update + Insert)といいます。 
 
 ON DUPLICATE KEY UPDATE 句を指定し、行を挿入すると、UNIQUE インデックスまたは PRIMARY KEY で値が 重複する場合、古い行の UPDATE をすることができます。 
 https://dev.mysql.com/doc/refman/8.0/ja/insert-on-duplicate.html 
 

  34. 社員情報削除エンドポイントを実装しよう
 56 処理内容
 メソッド
 パス
 リクエスト
 レスポンス
 BODY
 STATUS
 BODY(JSON形式)


    社員情報一覧取得
 GET
 /employee/
 なし
 200 OK
 全ての社員情報
 社員情報取得(ID指定) 
 GET
 /employee/:employeeId 
 なし
 200 OK
 社員IDに該当する社員情報 
 404 Not Found
 エラーメッセージ
 社員情報登録
 POST
 /employee/
 社員情報
 201 Created
 登録後の社員情報
 400 Bad Request
 エラーメッセージ
 社員情報更新
 PUT
 /employee/:employeeId 
 社員情報
 200 OK
 更新後の社員情報
 400 Bad Request
 エラーメッセージ
 404 Not Found
 エラーメッセージ
 社員情報削除
 DELETE
 /employee/:employeeId 
 なし
 204 No Content
 なし
 404 Not Found
 エラーメッセージ

  35. テーブル定義 EVALUATION(評価)
 カラム名(物理) 
 カラム名(論理) 
 型
 UK
 NOT NULL


    備考
 EMPLOYEE_ID
 社員ID
 VARCHAR(10)
 ✅
 ✅
 
 PERIOD
 評価期間
 VARCHAR(10)
 ✅
 ✅
 FY22H1, FY22H2 など 
 EVALUATION
 評価結果
 VARCHAR(10)
 
 ✅
 S, A, B, C, D
 MANAGER_COMMENT 
 上司コメント
 VARCHAR(256) 
 
 ✅
 
 CREATE_AT
 登録日時
 TIMESTAMP
 
 ✅
 DEFAULT CURRENT_TIMESTAMP 
 UPDATE_AT
 更新日時
 TIMESTAMP
 
 ✅
 DEFAULT CURRENT_TIMESTAMP 
 ON UPDATE CURRENT_TIMESTAMP 
 59
  36. Dockerコンテナ内のMySQLにconfidentialデータベースを作成する
 docker-compose.ymlには1つのデータベース設定しか適用できません。 
 
 employeesデータベースの設定を既に適用しているのでconfidentialはどうすれば良いでしょうか? 
 
 docker-entrypoint-initdb.dにSQLを配置すれば、Dockerコンテナ作成時にデータベース初期化を行なってくれる ことを学習しました。 


    
 それを利用して、新データベースを作成するSQLを作成してdocker-entrypoint-initdb.dに配置することで、データ ベースを初期化するようにしましょう。 
 
 ・03_confidential_schema.sql 
 ・04_confidential_data.sql 
 
 application.propertiesのデータベース接続情報も追加しましょう。 
 60
  37. 社員評価に関するエンドポイント 
 処理内容
 メソッド
 パス
 リクエスト
 レスポンス
 パラメータ
 STATUS
 BODY(JSON形式)


    社員評価取得
 GET
 /employee/evaluation/:employeeId 
 ?period=
 200 OK
 社員IDに該当する社員評価 
 複数データソースにアクセスできるような設定を実装する前に、おおよその下地を実装しておきましょう。 
 
 ・リクエストパラメータのperiodの指定は任意 
 ・社員評価レスポンス(EvaluationResponse)を作成 
 ・ServiceにfetchEvaluationを作成 
 ・MapperインターフェースにselectByIdAndPeriodを作成 
 ・EvaluationDtoを作成 
 ・MapperXMLにSELECT文を作成(動的SQL > if ) 
   https://mybatis.org/mybatis-3/ja/dynamic-sql.html#if-1 
 61
  38. 複数データソースの設定
 複数データソースを利用するための設定はどのようにすれば良いでしょうか? 
 
 ちょっとその前に、MyBatisの公式ドキュメントの[クイックセットアップ]を見ると、こんなことが書いてあります。 
 
 https://mybatis.org/spring/ja/getting-started.html 
 >

    MyBatis と Spring を組み合わせて使う場合、Springの Application Context 内に少なくとも 
 > SqlSessionFactory と一つ以上のMapperインターフェースを定義する必要があります。 
 > MyBatis-SpringではSqlSessionFactoryの生成にSqlSessionFactoryBeanを使います。 
 > この Factory Bean を設定するため、Springの設定ファイルに次のBeanを追加してください。 
 
 あれ?SqlSessionFactoryとかを設定した覚えはないですよね? 
 62
  39. 複数データソースの設定
 64 コンポーネント
 提供元
 どういうもの?
 DataSource
 Java
 アプリケーションからデータベース接続を提供するJavaのインター フェース。本講座ではDataSourcePropertiesから生成する。
 SqlSessionFactory


    MyBatis
 データベースへの一連の操作を保持するSQLセッションを生成し ます。SqlSessionFactoryBeanから生成し、DataSourceを設定しま す。
 SqlSessionTemplate
 MyBatis-Spring統合ライブラリ
 SqlSessionTemplateを設定することで、Springが提供するトランザ クション管理下でMyBatisのSqlSessionを実行します。
 DataSourceProperties
 SpringBoot
 データソースへの接続に必要な詳細情報(接続URL/ユーザ名/ パスワードなど)を管理することができるクラス。
 DataSourceTransactionMana ger
 Spring
 データベースのトランザクションを管理します。 SqlSessionTemplateと併用することでより厳格なトランザクション 制御が可能になります。

  40. 複数データソースの設定
 65 employeesデータベースに接続するための 下記必要な情報をBean登録 
 
 ・DataSource
 ・SqlSessionFactory 
 ・SqlSessionTemplate

    
 ・DataSourceProperties 
 ・DataSourceTransactionManager 
 
 confidentialデータベースも同様にConfigク ラスを定義しましょう。