Spring boot備忘録

# *2022/03/03*

***Spring***
〇処理の流れ
URLを入力する
→@Controllerのついたクラスの@RequestMappingの引数で指定したパス名（パスは絶対Or相対どちらも可）の戻り値がStringのメソッドに行く
→メソッド内で処理後、String型で遷移したいHTMLファイルを戻す。
→HTML内で画面入力や表示など

〇気づき
・@Seriviceでは、@Controllerで記述するとコードが煩雑になる処理を（ロジック処理）記述する。
いままでのクラス分けのようなもの。
・@RequestMappingの引数のparamsはあくまで値の有無を判別（booleanでのcheckのようなもの？）なので値を受け取りたいだけなら、内部のメソッドの引数で@RequestParamでパラメータ名に指定してやればよい。
・@ExceptionHandlerでcatchする対象のページでもExceptionをキャッチする必要は現場のルール確認

〇入力チェック
(1)
入力したURLの表示HTMLで、
フォーム内でエラーの対象を指定
→タグ内でエラーチェックで引っかかった際のクラスを記述。
※この時、コントローラでエラー処理できるようにFormにエラー処理を記述しておく。
→@RequestMappingで渡されたエラー内容をそのメソッドの引数で受け取る
→@ValidatedをつけたFormに入れ、同時にBindingResultも引数として指定
→メソッド内でBindingResultのhasError()メソッドでこの時点でエラーが存在していた際の遷移先を戻す。

〇入力チェックのアノテーション
入力チェックを行うフィールドに対して、Form内でアノテーションを用いた記述が必要。
ex)@Range、@Size、@Degits、@NotEmpty
上記注釈型には指定の引数があり、制限したい数値の範囲や値の判定に使用可能。
指定した後は、messageで{"指定の引数"}とすることでページに表示させれる。
ちなみに{0}は、対象のフィールド名。

〇message.properties
ここにエラーチェックしたいフィールドやアノテーション、型エラーを記述しておくと、FormやBindingResultのrejectを使用した入力チェックが可能。


# *2022/03/04*
リダイレクトしてSessionStatusのsetComplete()メソッドを使用したタイミングで セッション情報が破棄(JSPでいうところのinvalidate)される
セッション破棄してからのHTML遷移を狙うには一つ上のメソッドで setComplete()する必要がある
 破棄されるタイミングとしては、setComplete()が呼び出された時ではなく setComplete()が呼び出されたメソッドの処理が終了したタイミング
 呼び出された段階ではあくまでsetComplete()の予約が行われただけ
 ガベージコレクションと呼び出した段階の動作は似たような感じ
 また、個々のセッション管理をするにはサーブレットでの記述が必要
 以下サーブレットでの記述
//	@RequestMapping(value="/insert-list-sample")
//	public String setInsertList(HttpSession session) {
//		List<String> insertList =new ArrayList<String>();
//		session.setAttribute("insertListy", insertList);
//	}

値チェックなどで個々のフィールドのJava記法によりチェックをし、処理をページに表示させる場合、なるべく個々に処理が可能なrejectValueを使うべし

〇意識
***極力記述を減らせるのであれば減らす***

比較など値を直接表示したり使用しない場合（チェックにだけ使うなど）、該当する比較用メソッドの引数には、Bean全体の値を入れるのではなく、Beanの使う値だけを引数に入れること。

他クラスのメソッド使用時のインスタンス化やBeanのインスタンス化、特にデータベースと連携するメソッドのインスタンス化の際、条件によっては処理をしないなど余計なコードの記載はNG。
処理しないのに、数万件のデータベースの中身の検索を行ってしまったりと非効率だから。

変数の名前は精査する必要がある。
パット見てわからないものはNG。
自分でも少し前のコードは忘れているので意識しとけ。

〇Springのセレクトボックスの作成
・日付など繰り返し処理が必要なもの
Formに繰り返し処理を記載したgetterを記述。こいつに戻り値を設定しHTMLで使用する。
→
Controllerでセレクトボックスを実装する遷移先の処理メソッドで、Formをインスタンス化し、model.addAttributeしてパスを指定
→
遷移先のHTMLでFormの要素としてth:eachの繰り返し処理を行う。value,text共にoptionタグ中に記載。


# *2022/03/07*
〇気づき
１．message.propertiesを有効利用する。
HTMLの日本語べた書きしている部分は、変更や
国際化対応（英語対応）を踏まえて、<span>タグ等で囲んでmessage.propertiesから参照してやるとよい。可用性高まる。

２．Springの依存関係
今回実践演習１で行ったエラーチェックについて、チェッククラスに引数でサービスとBindingResultを渡していたが、これだと依存関係を減らしDIで管理するというSpringの利点を生かせない。
なので、まずBindingResultは戻り値でリストとしてコントローラに渡して、コントローラでループ処理＆表示。
Serviceはコントローラ側で書いてエラーチェック呼び出しとうまく組み合わせるか、DI（サービスクラス）に書いてコントローラに持ってくるか、する。
DIの意味合い的にはDB操作が行われるため、UIと関係ない→コントローラに書くべきではないかと。

３．Formのフィールド
値の受け渡しを行うフィールド以外はフィールド定義すべきではない。Formはあくまで、外部から参照を絶ったフィールドの書き換えや取得をするためのものだからである。
もしFormを使って値の加工をしたいのなら、フィールドとして定義せず、getterとして（状況によりsestterも？）フィールドを定義せずに直接戻り値に処理を書いてれやればよい。

４．MapperでのDB操作
以下の2点
・SELECTでWHERE句を使う際、条件分岐やLIKEでのワイルドカード処理をしないのなら,<WHERE>ではなく、普通のSQLのようにWHEREで書こう。
・INSERTで日付を扱う際はプレースホルダ同様CURRENT_DATEで書いてよし。もちろん他の構文も使える


# *2022/03/09*
〇
１．domainやパーシステンスについて
DBへのアクセス機能なので、どこから使われても問題ない→フォルダ分けせず同じフォルダに作っていく
テーブルごとに分けるとよい。インサートやアップデートは一回の記述→insertやupdateで済む。
インサートなどの引数には、なるべくdomainのもの使用。
domainはＤＢにないフィールドを持ち込まない。
意味合いが変わってしまう。


２．web
1機能1コントローラに基づくならば、web直下に機能ごとのフォルダを作成して、コントローラも適宜分ける。
resourcesと一対一になるようにするとベター。


３．messages
テキスト表示のみを狙うものは「label.＊＊」のようにあらわすとわかりやすい。
ボタンも機能を最初に記入してやると良い。
「button.＊＊」


４．addAttribute
サーブレットのsetAttribute同様、何個でも送れる
なぜか→Mapのように一意の値としてキーが設定されているためJava側も判断に迷うことがないため許可されている。


５．エラーログ
バグを検知するための非常に重要な要素。
ログに詳細が出力されず、解消に困ったときは表示されるログからあたりをつけてみるORログをコピってググってみる。


６．別のURLからの値遷移と似たやり方で、同じURLに対して別のページの表示が可能


# *2022/03/10-11*
１．@Transactional
複数のテーブルに対して、登録上書き削除を行う際は、整合性を保つために、トランザクション制御が必要。
このアノテーションを使用すると今まで手書きで行っていた、setAutoCommitやrollback.commitを自動で行ってくれる。一人のプロジェクトでも必須事項。



２．DBの呼び出し処理
DBからSELECTしたデータはセッションにかくのうすれば使いまわすことができる。しかしこのDB情報はあくまでSELECTした時点でのデータであるため、他のユーザがINSERTやDELETEをしていればデータが変わってしまう。そのため、DB情報を表示したい場合はデータを最新の状態に保つため、毎回DBに接続して呼び出したほうが良い。
ただし、DBへのアクセス権限が一人のみだったり、2人以上のDBアクセスが検知されたら最初のユーザを強制ログアウトさせるなどの処理がなされるのであれば、この限りではない。



３．input type=textの初期値
placeholderを使用すると、薄文字で表示可能



４．日時表示の加工方法
例として、日時を「00」のように常に2桁で扱いたいときはString.format((1),(2))を使用する。
(1)には書式文字列
　　　　…%　書式文字列をあらわす
　　　　…0　今回は0で埋めるため0
　　　　…2　今回は2桁のため2
　　　　…d　整数はd、文字列はs、その他諸々
(2)には加工する値
　　　　…参照型も可
をセット。


# *2022/03/22*
〇リダイレクト時のパラメータの受け渡し
requestではないため@RequestParamは使えない。
RedirectAttributesのaddFlashAttributeを使用してリダイレクト先にパラメータを渡す。

〇scopedTarget
セッションに↑を定義した場合、本コントローラ内では値を保持しながら渡せず勝手にセッションが破棄される。
逆に本コントローラの外に置いた場合には値が保持され続ける。


# *2022/03/25*
〇MybatisでのSQLの格納
マップに格納する際、Map<K,V>では値が格納されない。
右記記述で解決→Map<K,Map<V,Object>>

〇MybatisとJavascriptを埋め込んだThymeLeaf
コントローラから送信した値をJavascriptでコメントアウト(/**/)内にThymeLeafの形(${値})で記述。
その後、functionメソッド内で回していく。以下で指定。
→Object.keys(d).forEach(function(key){ data.addRow([ key, d[key]]); });

データは配列でしか表示できないため、渡す際は配列型かjava.util.Mapにして渡す。
家計簿では、以下のように加工した。
1．MyBatisのXMLでSQLを記述。ResultMapを用いてカテゴリ名と入金額の合計をInfoにマッピング。
2．マッピング後、List<**Info>インターフェースを定義。
3．Serviceでマッピングした値を2.インターフェースをオーバーライドしたメソッドで呼び出す。
4．受け取ったListを拡張for文で回してMapに格納。
5．格納時Infoの値をGetterで取得して格納。値が重複しないようputIfAbsentで格納している。
6．コントローラに渡してビューへGO


# *2022/03/26*
〇spring bootのセッション
正直ふわっとした理解レベルなので再度体系的に理解する必要がある。
ただ進捗はあった。
気づいたのだが、毎度毎度持ち回るのではなく、setCompleteなどセッション情報が破棄されてしまうためどうしても持ち回れないときに、前後で保持処理を行って、その後FormなりBeanなりに再格納すればOK。

再理解のため、以下の本で学習してみる？
spring boot解体新書