Spring Boot DB連携

Spring BootのWEB画面上でファイルダウンロード処理とDB更新処理を併用してみた

今回は、以前実装していたSpring BootのWEB画面上でファイルダウンロード処理に、DB更新処理を追加してみたので、そのサンプルプログラムを共有する。

ファイルダウンロードを行う際、最後にInputStreamオブジェクト, OutputStreamオブジェクトをそれぞれcloseする必要があるが、エラー発生時でも確実にcloseできるようにするには、finally句でこれを実行する必要がある。

例えばプログラム上で、DB更新⇒ファイルダウンロードの順に記載している場合、DB更新処理・ファイルダウンロード処理がほぼ同じタイミングで実行されるため、finally句でclose処理を実行しないと、DB更新処理に失敗した場合にclose処理が実行されなくなってしまう。

今回は、下記「前提条件」に記載した記事に、finally句でclose処理を実行する部分と、ファイルダウンロード前のチェック処理の追加を行ったので、その内容について共有する。



前提条件

下記記事の実装が完了していること。

Spring BootのWEB画面上でPDFプレビューを実装してみた前回は、Sping BootのWEB画面上で、ファイルアップロード・ファイルダウンロード機能について記載したが、今回は、PDFの場合のみ...

完成イメージ

ここでは、完成した画面イメージの共有を行う。

Spring Bootアプリケーションを起動し、「http:// (ホスト名):(ポート番号)」とアクセスした場合の初期表示は以下の通りで、「PDFプレビュー」ボタンを押下すると、以下のように、別画面にPDFプレビュー画面が表示されると共に、ダウンロード履歴テーブルにレコードが1件追加される。
ダウンロード履歴作成_実行結果1

ダウンロード履歴作成_実行結果2

ダウンロード履歴作成_実行結果3
なお、ダウンロード履歴テーブルは、本記事で作成するものとする。

また、「ダウンロード」ボタンを押下すると、以下のように、画面下にファイル操作のダイアログが表示されると共に、ダウンロード履歴テーブルにレコードが1件追加される。
ダウンロード履歴作成_実行結果4_1

ダウンロード履歴作成_実行結果4_2 ダウンロード履歴作成_実行結果5

ダウンロード履歴作成_実行結果6

さらに、一覧に表示されるものの、ファイルダウンロードデータが無い場合は、以下のように、ダウンロードエラー画面が表示される。
ダウンロード履歴作成_実行結果7

ダウンロード履歴作成_実行結果8

なお、上記の場合は、ダウンロード履歴テーブルへのレコード追加はされない。



やってみたこと

  1. ファイル履歴テーブルとそのシーケンスの作成
  2. サンプルプログラムの作成

 

ファイル履歴テーブルとそのシーケンスの作成

今回は、ファイル履歴テーブルとそのシーケンスを追加した。実行したSQLは以下の通り。

実行後の確認結果は以下の通り。テーブルの確認はdescコマンドで、シーケンスの確認はuser_sequencesテーブルで、それぞれ確認している。

desc_ダウンロード履歴テーブル

select_user_sequences



サンプルプログラムの作成

今回作成したサンプルプログラムの構成は以下の通り。なお、下図の赤枠は、前提条件に記載した記事と変更になったソースコードを示しており、今後記載する。
サンプルプログラムの構成

ダウンロード履歴テーブルにアクセスするためのエンティティクラスは以下の通り。



また、ダウンロード履歴テーブルにアクセスするためのMapperインタフェースは以下の通り。今回はシーケンスの採番も行っているので、そのselect文も含めている。

さらに、コントローラクラスは以下の通り。ここでは、downloadメソッド内で、エラーチェック処理とダウンロード履歴テーブルへの登録処理を追加している。また、InputStreamオブジェクト, OutputStreamオブジェクトのclose処理はfinally句で実装している。

さらに、ダウンロードエラー時は、ダウンロードエラー画面に遷移する。ダウンロードエラー画面の実装は以下の通り。

その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-download-updatedb/demo

要点まとめ

  • ファイルダウンロード時の、InputStreamオブジェクト, OutputStreamオブジェクトのclose処理は、例外発生の可能性がある場合は、finally句で実装する必要がある。