質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

1回答

5216閲覧

SpringMVCの@ModelAttributeで毎回初期化されるのが無駄に感じます。

msss

総合スコア33

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

0グッド

0クリップ

投稿2018/05/25 13:27

編集2018/05/25 13:28

環境

xml

1<parent> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-parent</artifactId> 4 <version>2.0.1.RELEASE</version> 5 <relativePath /> <!-- lookup parent from repository --> 6</parent>

以下のページを見ました

https://sites.google.com/site/soracane/home/springnitsuite/spring-mvc/04-ji-ben-gai-nian-controllerno-chu-lifuro

サンプルとして載っているコード

java

1@ModelAttribute("user") //②モデルの前処理 2public User newRequest(@RequestParam(required=false, value="id") String id) { 3 if(id== null) return null; 4 return this.accountService.get(id); 5}

以下が無駄だと思う理由です

(1).@ModelAttributeの呼び出し  : 事前準備として、DBからPOJOを取得して、Model に登録します。

(ModelAttributeメソッドでDBからPOJOを取得し、RequestMappingメソッドを呼び出すときにSpringが自動的に画面の値で必要なPOJOフィールドを更新する)

  • 調べてみたら確かに@RequestMappingの前に必ず@ModelAttributeが呼ばれて初期化する事を確認しました。
  • また、説明通り@RequestMappingで受け取るformは画面の値で上書きされていました。

画面の値で上書きするのであれば毎回初期化するのは無駄に感じます。
※特にDBにアクセスする場合は毎回SQL発行する事になる為

また、if(id== null) return null; に関して、初期化が必要ない場合はidが入ってこないからnullを返しているのかと考えましたが、'@ModelAttribute'でreturn null;してしまうと@RequestMappingの引数で受け取るformnullになってしまうためvalidate処理や画面表示が正しく行われない為目的は違うんだろうと判断しました。

みなさん気にならずにそのまま実装しているのでしょうか、または別の方法で実装されているのでしょうか。

以下ならまだわからないでもないです

java

1@ModelAttribute("user") //②モデルの前処理 2public User newRequest( @RequestParam(required=false, value="id") String id, User form) { 3 if(id== null) return form; 4 User user = this.accountService.get(id); 5 BeanUtils.copyProperties(user, form); 6 return form; 7}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/05/25 14:31

つまり 1を変更した後に 存在しない2を変更しようとして1が更新された方がいいと?
guest

回答1

0

ベストアンサー

画面の値で上書きするのであれば毎回初期化するのは無駄

ここに認識の誤りがあるでしょう。参照されたサイトの「掲載されているコード」全部を見ると、

リクエストパラメータ(id, nameの2つ)を受け取り、

  • idが未指定なら検索しない→Controllerの本体へ
  • idに何らかの値があった場合はUserを取得→Controllerの本体へ

java

1 @ModelAttribute("user") 2 public User newRequest( 3 @RequestParam(required=false, value="id") String id, 4 ) { 5 if(id== null) return null; 6 return this.accountService.get(id); 7 }

Userにはid,name以外のフィールドがあるが(feeId)、画面から受け取るのはid, nameだけである。

java

1 @InitBinder("user") 2 public void initBinder(WebDataBinder binder) { 3 binder.setAllowedFields("id", "name"); 4 }

Controller本体の処理は以下

java

1 @RequestMapping(value="/accountEdit", method=RequestMethod.POST) 2 public String form(@Valid @ModelAttribute("user") User user, BindingResult result) { 3 if(result.hasErrors()){ 4 return "account-edit-input"; 5 } 6 this.accountService.updateUser(user); 7 return "account-edit-complete"; 8 }

なので、流れとしては以下ですね。AccountServiceの作りを変えない前提ならば、特に無駄はありません。

  1. リクエストパラメータにidが指定されていれば、idを元にUserを検索
  2. Controllerの本体へ処理が移動したときは、1で取得したUserのnameにリクエストパラメータの内容が入る( idは検索時と同じ ) このとき、該当するUserが取得できていなければUserはnullになる。
  3. accountServiceのupdateUser(user) で更新する

ところで、

以下ならまだわからないでもないです

のコードを拝見しましたが、

this.accountService.updateUser(user) が抜けていませんか?

投稿2018/05/26 02:20

A-pZ

総合スコア12011

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

msss

2018/05/27 01:56

回答ありがとうございます。 わかりやすい解説をしていただいたことで頭の中が整理できました。 ・idが入っていない=エラーのため"account-edit-input";に遷移させる。 ・idが入っている場合画面入力値以外の項目(feeId)も更新に必要なので取得してリクエストパラメータで上書きして更新 確かに、SampleControllerクラスに@RequestMappingのメソッドが1つしかないので無駄に感じませんでした。 例えば @RequestMappingが複数あった場合、@ModelAttributeが呼び出される度にDBアクセスが必要ない場合、@RequestMappingにDBアクセス処理を書くというイメージを持っていますが、間違っているでしょうか。 ※ 以下の内容から、@ModelAttributeでは画面に必要なデータをDBから取得するというイメージを持ってしまいましたが、時と場合(画面設計)によるということでよいでしょうか。 >【通常のControllerの処理の流れ】 >(1).@ModelAttributeの呼び出し  : 事前準備として、DBからPOJOを取得して、Model に登録します。
退会済みユーザー

退会済みユーザー

2018/05/27 22:25

はっw entityを直接 form として利用するソースなのか
msss

2018/05/28 02:34

ご指摘ありがとうございます。 entity=formついては確かに疑問を感じる点はありましたが今回は気にしませんでした。
A-pZ

2018/05/28 10:15

無駄になるかどうかは、Controller~Serviceの設計次第ではありますね。 実際、 ModelAttributeにて実際に検索するのはトリッキーなコードにも思えます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問