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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

JDBC

JDBC(Java DataBase Connectivity)は、Javaとリーレーショナルデータベースに接続させる基本的なAPIです。Java上でSQLステートメントを発行することで、データベースの種類に影響を受ないDB操作を可能とします。

Java

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

Spring

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

Q&A

解決済

3回答

3454閲覧

queryForListがうまくいきません。

usako

総合スコア31

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

JDBC

JDBC(Java DataBase Connectivity)は、Javaとリーレーショナルデータベースに接続させる基本的なAPIです。Java上でSQLステートメントを発行することで、データベースの種類に影響を受ないDB操作を可能とします。

Java

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

Spring

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

0グッド

0クリップ

投稿2019/05/28 01:59

編集2019/05/28 06:24

前提・実現したいこと

Eclipse,Springを使ってJAVAの勉強をしている(超)初心者です。
元々、受講していた通信教育の課題がDBを使用しておらず、
内部にテーブルを保持している構造だったので、それを
MySQL,jDBCで外部化しようとしています。
一覧表示、更新、参照機能だけのシンプルな画面です。
まずは一覧機能を実装しようとしたところ、NULL例外で以下のメッセージが
発生しました。エラーの原因個所は特定できました。
List<Map<String, Object>> list1 = jdbcTemplate.queryForList("select * from unit02.addressbook");
ただ、この記述のどこに問題があってNULLが発生しているのかがわかりません。
DBにはデータも存在します。
どなたか、ご教授いただけないでしょうか。

発生している問題・エラーメッセージ

HTTPステータス 500 - Request processing failed; nested exception is java.lang.NullPointerException type 例外レポート メッセージ Request processing failed; nested exception is java.lang.NullPointerException 説明 The server encountered an internal error that prevented it from fulfilling this request. The server encountered an internal error that prevented it from fulfilling this request.

該当のソースコード

Java

1package jp.practice.address; 2 3import java.util.List; 4import java.util.Map; 5 6import org.springframework.stereotype.Controller; 7import org.springframework.ui.Model; 8import org.springframework.web.bind.annotation.RequestMapping; 9/**e n d*/ 10 11@Controller 12@RequestMapping(value = "/book") 13public class AddressBookController { 14 private static final String INIT = "init"; 15 private static final String REFER = "refer"; 16 private static final String UPDATE = "update"; 17 private static final String LIST = "list"; 18 private static final String INIMSG = "従業員番号を入力してください"; 19 private static final String REFMSG = "情報が取得できました"; 20 private static final String UPDMSG = "情報を更新してください"; 21 private static final String ERRMSG = "該当するデータはありません"; 22/**start ****/ 23// @Autowired 24// private JdbcTemplate jdbcTemplate; 25/**e n d*/ 26 @RequestMapping(value = "/start") 27 public String init(AddressBookForm form, Model model) { 28/**start ****/ 29// List<Map<String, Object>> list = jdbcTemplate.queryForList("select * from unit02.addressbook"); 30// for (int idx1 = 0; idx1 < 13; idx1++){ 31// System.out.print(idx1); 32// model.addAttribute("id", list.get(idx1).get("id") ); 33// model.addAttribute("name", list.get(idx1).get("name") ); 34// model.addAttribute("tel", list.get(idx1).get("tel") ); 35// model.addAttribute("address", list.get(idx1).get("address") ); 36// } 37/**e n d*/ 38 model.addAttribute("message", INIMSG); 39 return INIT; 40 } 41 42 @RequestMapping(params = "reference") 43 public String refer(AddressBookForm form, Model model) { 44 Employee employee = RecordManager.selectEmployee(form.getId()); 45 if (employee != null) { 46 form.setName(employee.getName()); 47 form.setPhone(employee.getPhone()); 48 form.setAddress(employee.getAddress()); 49 model.addAttribute("message", REFMSG); 50 return REFER; 51 } else { 52 model.addAttribute("message", ERRMSG); 53 return INIT; 54 } 55 } 56 57 @RequestMapping(params = "toInit") 58 public String toInit(AddressBookForm form, Model model) { 59 model.addAttribute("message", INIMSG); 60 return INIT; 61 } 62 63 @RequestMapping(params = "update") 64 public String update(AddressBookForm form, Model model) { 65 Employee employee = RecordManager.selectEmployee(form.getId()); 66 if (employee != null) { 67 form.setName(employee.getName()); 68 form.setPhone(employee.getPhone()); 69 form.setAddress(employee.getAddress()); 70 model.addAttribute("message", UPDMSG); 71 return UPDATE; 72 } else { 73 model.addAttribute("message", ERRMSG); 74 return INIT; 75 } 76 } 77 78 @RequestMapping(params = "reflection") 79 public String reflection(AddressBookForm form, Model model) { 80 Employee employee = new Employee(form.getId(), form.getName(), form.getPhone(), form.getAddress()); 81 RecordManager.updateEmployee(employee); 82 model.addAttribute("message", INIMSG); 83 return INIT; 84 } 85 86 @RequestMapping(params = "list") 87 public String list(Model model) { 88 List<Map<String, Object>> employeeList = RecordManager.getEmployeeList(); 89 model.addAttribute("employeeList", employeeList); 90 model.addAttribute("employeeCount", employeeList.size()); 91 return LIST; 92 }

Java

1package jp.practice.address; 2 3import java.util.ArrayList; 4import java.util.List; 5import java.util.Map; 6 7import org.springframework.beans.factory.annotation.Autowired; 8import org.springframework.jdbc.core.JdbcTemplate; 9/**e n d*/ 10 11public class RecordManager { 12/**start ****/ 13 @Autowired 14 private static JdbcTemplate jdbcTemplate; 15/**e n d*/ 16// /** 初期値データ */ 17 private static List<Employee> list = new ArrayList<>(); 18 static { 19// list.add(new Employee("200101", "佐藤一郎", "0569-000-1111", "尾張県愛知市舟船町596")); 20// list.dd(new Employee("200102", "鈴木次男", "0242-000-2222", "三河県三河市海池2727")); 21// list.add(new Employee("200103", "田中信三郎", "0722-000-3333", "和泉県泉市浜川55")); 22// list.add(new Employee("200104", "高橋四郎", "0729-000-4444", "摂津府兵庫市沼地11")); 23// list.add(new Employee("200105", "渡辺五郎", "0982-000-5555", "筑紫県筑後市泉町2")); 24// list.add(new Employee("200106", "伊藤六次", "0562-000-6666", "信濃県信州市泊町333")); 25// list.add(new Employee("200107", "山本七三", "086-000-7777", "土佐県四国市港町4")); 26// list.add(new Employee("200108", "中村八吉", "0489-000-8888", "薩摩県種島市潮見55")); 27// list.add(new Employee("200109", "小林九兵", "0827-000-9999", "周防県周防市川原66")); 28// list.add(new Employee("200110", "加藤十重", "048-000-1010", "武蔵県北むさし市河岸777")); 29// list.add(new Employee("200111", "ジャック", "0273-000-1111", "相模県相模市堤5")); 30// list.add(new Employee("200112", "山田十二", "075-000-1212", "駿河県南駿河市河口35")); 31 } 32 33 private RecordManager() { 34 } 35 36 /** 37 * 指定したID のレコードを取得 38 * 39 * @param id 40 * 従業員番号 41 * @return Employee 42 */ 43 44 public static Employee selectEmployee(String id) { 45 int index = list.indexOf(new Employee(id, "", "", "")); 46 if (index < 0) { 47 return null; 48 } 49 return list.get(index); 50 } 51 /** 52 * 指定した従業員情報を反映 53 * 54 * @param emp 55 * 従業員情報 56 */ 57 public static void updateEmployee(Employee emp) { 58 int index = list.indexOf(emp); 59 list.set(index, emp); 60 } 61/**start ****/ 62 public static List<Map<String, Object>> getEmployeeList() { 63 List<Map<String, Object>> list1 = jdbcTemplate.queryForList("select * from unit02.addressbook"); 64 65 return list1; 66/**e n d*/ 67 }

JSP

1<%@ page session="false" language="java" 2 contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 3<%@ page import="java.time.LocalDate"%> 4<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 5<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%> 6<!DOCTYPE html> 7<html> 8<head> 9<link rel="stylesheet" type="text/css" 10 href="/address/resources/css/common.css" /> 11<title>住所録(初期画面)</title> 12</head> 13<body> 14 <form:form modelAttribute="addressBookForm" action="/address/book"> 15 <div class="header"> 16 <span class="titleName">住所録</span> 17 <div class="date"><%=LocalDate.now()%></div> 18 </div> 19 <div class="main"> 20 <div class="message"> 21 <c:out value="${message}" /> 22 </div> 23 <div> 24 <span class="itemName">従業員番号:</span> 25 <form:input path="id" size="31" /> 26 </div> 27 </div> 28 <div class="footer"> 29 <div> 30 <input type="submit" name="reference" value="参照" /> 31 </div> 32 <div> 33 <input type="submit" name="update" value="更新" /> 34 </div> 35 <div> 36 <input type="submit" name="list" value="一覧" /> 37 </div> 38 </div> 39 <!-- start --> 40 <!-- <p> DB's id: ${id} name: ${name} tel: ${tel} address: ${address} . </p> --> 41 <!-- end --> 42 </form:form> 43</body> 44</html>

JSP

1<%@ page session="false" language="java" 2 contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> 3<%@ page import="java.time.LocalDate"%> 4<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 5<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%> 6<!DOCTYPE html> 7<html> 8<head> 9<link rel="stylesheet" type="text/css" 10 href="/address/resources/css/common.css" /> 11<title>住所録(一覧画面)</title> 12</head> 13<body> 14 <form:form modelAttribute="addressBookForm" action="/address/book"> 15 <div class="header"> 16 <span class="titleName">住所録</span> 17 <div class="date"><%=LocalDate.now()%></div> 18 </div> 19 <div> 20 社員数 : 21 <c:out value="${employeeCount}"></c:out> 2223 </div> 24 <table> 25 <tr> 26 <th>従業員番号</th> 27 <th>名前</th> 28 <th>電話番号</th> 29 <th>住所</th> 30 </tr> 31 <c:forEach items="${employeeList}" var="employee" varStatus="status"> 32 <c:choose> 33 <c:when test="${status.count % 2 == 0}"> 34 <tr class="even"> 35 <td>${employee.id}</td> 36 <td>${employee.name}</td> 37 <td>${employee.phone}</td> 38 <td>${employee.address}</td> 39 </tr> 40 </c:when> 41 <c:otherwise> 42 <tr> 43 <td>${employee.id}</td> 44 <td>${employee.name}</td> 45 <td>${employee.phone}</td> 46 <td>${employee.address}</td> 47 </tr> 48 </c:otherwise> 49 </c:choose> 50 </c:forEach> 51 </table> 52 <div class="listFooter"> 53 <input type="submit" name="toInit" value="戻る" /> 54 </div> 55 </form:form> 56</body> 57</html>

試したこと

AddressBookController.javaの@Controller直下だと、エラーにならずDBの内容を表示できます。
(現在はコメント化しています)

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

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

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

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

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

rubytomato

2019/05/28 13:23

@Autowired private static JdbcTemplate jdbcTemplate; の箇所でJdbcTemplateのインスタンスがセットされていないのではないでしょうか? getEmployeeListメソッドで、jdbcTemplate.queryForListを使う直前にjdbcTemplateがnullかどうか確認して結果をお知らせください。 たとえば if (jdbcTemplate == null) { System.out.println("jdbcTemplate is null"); } など。
usako

2019/05/29 00:53 編集

ご教授いただいたように、if文をいれたところ、"jdbcTemplate is null"と表示されました。 本来であれば何が入っているはずなのでしょうか。 また、何が原因でnullが入ってしまうのか、ご教授いただけないでしょうか。
guest

回答3

0

ベストアンサー

ご確認ありがとうございます。

if文をいれたところ、"jdbcTemplate is null"と表示されました。
本来であれば何が入っているはずなのでしょうか。
また、何が原因でnullが入ってしまうのか、ご教授いただけないでしょうか。

本来であればJdbcTemplateクラスのインスタンスが注入されているはずですが、nullになってしまう原因は下記のようにjdbcTemplateフィールドがstaticだからのようです。

@Autowired private static JdbcTemplate jdbcTemplate;

過去にも同じような質問がありましたのでご確認ください。

リンク先のページではstaticフィールドにautowiredする方法が紹介されていますが、staticを使わなくても解決できる方法もありますので、ここではその方法を記述します。なお、staticを使うか使わないかは設計の問題になると思いますので、どちらが正しい/間違っているという風には決められません(と思っていますが、私自身はなるべくstaticフィールドにならないようにしています)。

それでは下記にstaticを使わない方法の改修について説明します。改修点は大きく分けて2つあります。
1つ目がRecordManagerクラスの改修です。改修箇所にコメントを付けていますのでご確認ください。

// (1) Componentアノテーションを追加、これでSpring DIコンテナの管理下に入ります。 @Component public class RecordManager { // (2) Autowiredアノテーションとstaticを削除しました。 private JdbcTemplate jdbcTemplate; // (3) コンストラクタインジェクションという方法でJdbcTemplateを注入(autowired)します。 public RecordManager(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } // (4) staticを削除しました。 public List<Map<String, Object>> getEmployeeList() { List<Map<String, Object>> list1 = jdbcTemplate.queryForList("select * from unit02.addressbook"); return list1; } }

2つ目がRecordManagerクラスのインスタンスを利用するAddressBookControllerクラスの改修です。

@Controller @RequestMapping(value = "/book") public class AddressBookController { // (1) JdbcTemplateの代わりにRecordManagerを使用します。 private RecordManager recordManager; // (2) コンストラクタインジェクションです。 // RecordManagerはSpringの管理下にあるので注入してもらえます。 public AddressBookController(RecordManager recordManager) { this.recordManager = recordManager; } @RequestMapping(value = "/start") public String init(AddressBookForm form, Model model) { // (3) RecordManagerのインスタンスを使ってDBアクセスを行います。 List<Map<String, Object>> list = recordManager.getEmployeeList(); for (int idx1 = 0; idx1 < 13; idx1++){ System.out.print(idx1); } model.addAttribute("message", INIMSG); return INIT; } }

なお、コンストラクタインジェクションの部分ですが、従来通りフィールドにAutowiredアノテーションを付けて注入するという方法でも問題ありません。

@Autowired private RecordManager recordManager;

上記の内容で動作すると思うのですが、実際に環境を構築して動かした訳ではないので保証はできません。このコードを参考にして動かしたときに別の新しいエラーがでましたら、質問内容に追記ください。

2019/06/01追記

①RecordManage.java(1)において、@Componentを記載することnewせずともRecordManageというインスタンスが生成されるという理解で合っておりますでしょうか。

そのご理解で問題ないと思いますが、すこし補足しますとRecordManagerのインスタンスを使うには、誰かがnewしなければなりません。
その誰かを、Componentアノテーションを付加することでSpringに任せています。

Springは、アプリケーション起動時にComponentアノテーションが付加されたクラスを探し出しインスタンスを生成し管理します。
なお、Componentアノテーション以外にも下記のアノテーションが付加されたクラスが同様にインスタンス生成されます。
(他にもありますが、ここでは省略します。)

@Controller
@Service
@Repository

Controllerアノテーションは、コントローラクラスに付加されているのをご覧になっていると思いますが、コントローラクラスのインスタンス生成もSpringが行っています。

@Controller @RequestMapping(value = "/book") public class AddressBookController { //...省略... }

Springは自分が生成したインスタンスを管理していて、そのインスタンスが必要な場面がくるとそこへ注入(Injection)します。
必要な場所とは、ご存知の通りAutowiredアノテーションが付いているフィールドやメソッドなどです。

Springがサポートする注入の方法は3つあります。

  1. フィールドインジェクション

フィールドインジェクションを呼ばれる注入方法です。記述するコード量が少なくて済むのでこの書き方が多いように思います。

@Autowired private JdbcTemplate jdbcTemplate;
  1. セッターインジェクション

クラスを作成したときにフィールドにゲッター(getXXXX)/セッター(setXXXX)メソッドを書いたことがあるかと思いますが、このセッターメソッドを使う方法です。
Autowiredはセッターメソッドに付けます。
なお、私の経験上ですがセッターインジェクションが使われているコードはあまり見たことがありません。

private JdbcTemplate jdbcTemplate; @Autowired public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate }
  1. コンストラクタインジェクション

名前の通りクラスのコンストラクタを使った注入方法です。
コンストラクタが1つだけの場合はAutowiredアノテーションを省略することができます。が、書いてもエラーではありません。

private JdbcTemplate jdbcTemplate; // @Autowired 付けなくてもよい public RecordManager(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; }

上記のとおり、Component(やController,Service, Repository)とAutowiredアノテーションを利用することで、インスタンスの生成と注入を任せることができますが、1点気を付けなければならない点があります。
それは、Springは自身が生成したインスタンスに対してのみインスタンスの注入を行うということです。
このご質問のRecordManagerクラスのJdbcTemplateフィールドがnullになってしまう理由は、RecordManagerのインスタンス生成をSpringが担当していなかったからということになります。

ざっくりとした説明になりましたが、この機能はSpring Frameworkの重要な機能の1つでDI (Dependency Injection) / "依存性の注入"と呼ばれています。ネットで検索すれば詳しい記事がたくさんみつかるとおもいますので探して読んでみてください。
あるいは書籍で知識を仕入れるのも最初のころはいいかもしれません。

②RecordManage.java(3)において、コンストラクタインジェクションにする意図。jdbcTemplateを動的に注入して・・・ということだと考えていますが、コンストラクタインジェクションを行わない場合、どのようなことが起こりえるのでしょうか。(テストのしやすさとかの問題だけ?)

こちらの意味は、コンストラクタインジェクションとフィールドインジェクションの違い(メリット/デメリット)は何か?という風に解釈しましたが、その前提で進めます。

上記で触れていますが、注入(Injection)方法には3つあります。これらは場面によって使い分けるものと私自身は考えていますが、Springの開発チームは
”つねにコンストラクタインジェクションを使う”ことをお勧めする(Recommend)というメッセージを出しています。

このようなメッセージを出す背景には、コンストラクタインジェクションのメリットが大きいからだと思いますが、テストコードが書きやすくなるのもその1つだと思います。
他にもありますが、私自身上手くご説明できないので、"spring コンストラクタインジェクション フィールドインジェクション"などのキーワードで探してみてください。すぐに詳しく解説してくれているページがすぐに見つかると思います。

もし探したページをいくつか読んでも腑に落ちないということであれば、Spring Frameworkはかなり大きなプロジェクトなので前提となる知識が不足しているのかもしれません。
そんなときは先にJavaでコードを書く時のベストプラクティスを習得するという方向に向かうのもいいと思います。(並行して簡単なSpringを使ったアプリケーションを書き続けるのもなお効果があるとおもいます)

③AddressBookController.java(2)において、コンストラクタを追加していますがこれはRecordManage.java(3)で作成したコンストラクタを受け取るためのものという理解で合っておりますでしょうか。

RecordManage.java(3)で作成したコンストラクタを受け取るためのもの

ここの”コンストラクタを受け取る”とはどういう意味なのかちょっと分かりませんが、AddressBookControllerクラスにコンストラクタを追加したのは、SpringにRecordManagerのインスタンスを注入してもらうためです。(コンストラクタインジェクションを使って)
上記で触れていますが、RecordManagerクラスにComponentアノテーションを付加したことによりSpringがインスタンスを生成、管理してくれています。

2019/06/04 追記

質問の意図としては、jdbcTemplateがRecordManagerクラスに注入され、更にrecordManagerがAddressBookControllerクラスに注入されるという具合に値(オブジェクト?)が引き継がれていくのでしょうか、ということでした。

"引き継がれていくのでしょうか"という表現は多少違和感(聞きなれない表現なので)がありますが、概ねそのような理解で良いかと思います。

コンストラクラインジェクションと普通の引数ありのコンストラクタの見極めはどのように行うのでしょうか。(記述方法としては同じになると思うのですが・・・)
デフォルトコンストラクタが見当たらないのもなぜなのかわかりません。これもSpringが勝手にやってくれているということなのでしょうか。

クラスにコンストラクタを1つも定義しなかった場合、暗黙的に引数無し、処理なしのコンストラクタが定義されます。これがいわゆるデフォルトコンストラクタと呼ばれるものです。
この動きはJavaの言語仕様でSpringは関係ありません。

以下の1)と2)は同じコードと言えます。コンストラクタを1つも定義しなかった場合、1)には2)のような引数無し、処理なしのコンストラクタが(ソースコード上は見えませんが)追加されます。

java

1@Controller 2public class AddressBookController { 3 4 // コンストラクタを明示的に定義しなかった場合、ソースコード上には見えないが 5 // 引数無し、処理なしのデフォルトコンストラクタが暗黙的に定義される 6 7}
@Controller public class AddressBookController { // デフォルトコンストラクタ public AddressBookController() { } }

ただし、3)のようにクラスに明示的にコンストラクタを追加すると、引数無し、処理なしのデフォルトコンストラクタは追加されません。これもJavaの言語仕様です。
コンストラクタが1つだけの場合、Springはそのコンストラクタを使ってコントローラクラスのインスタンスを生成します。

@Controller public class AddressBookController { private RecordManager recordManager; // RecordManagerがSpringの管理下にある場合、管理しているインスタンスを引数に渡す public AddressBookController(RecordManager recordManager) { this.recordManager = recordManager; } }

次に明示的にデフォルトコンストラクタを定義し、コンストラクタを2つにした場合どうなるかというと
Springはデフォルトコンストラクタを使用してコントローラクラスのインスタンスを生成するので、4)の例で言えばrecordManagerフィールドはnullになります。

@Controller public class AddressBookController { private RecordManager recordManager; public AddressBookController() { } public AddressBookController(RecordManager recordManager) { this.recordManager = recordManager; } }

引数有りのコンストラクタを使ってほしい場合は以下のようにコンストラクタにAutowiredアノテーションを付加します。
SpringはAutowiredアノテーションが付いたコンストラクタを使ってコントローラクラスのインスタンスを生成、その際にRecordManagerのインスタンスを引数に与えます。

@Controller public class AddressBookController { private RecordManager recordManager; public AddressBookController() { } @Autowired public AddressBookController(RecordManager recordManager) { this.recordManager = recordManager; } }

引数の数が違うコンストラクタを定義し、そこにもAutowiredアノテーションを付加した場合どうなるかですが
コンストラクタにつけられるAutowiredアノテーションは1つまでなのでエラーになります。

@Controller public class AddressBookController { private RecordManager recordManager; public AddressBookController() { } // これはエラー @Autowired public AddressBookController(RecordManager recordManager) { this.recordManager = recordManager; } // これもエラー @Autowired public AddressBookController(RecordManager recordManager, String dummyParam) { this.recordManager = recordManager; } }

投稿2019/05/29 07:42

編集2019/06/04 13:00
rubytomato

総合スコア1752

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

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

usako

2019/05/30 01:58

rubytomato様、丁寧な回答ありがとうございます!この通りにプログラムを修正したら、正常に動作するようになりました。ただ、修正の意図がわからない個所があります。(主にコンストラクタインジェクション)ネットや本でも調べてみたのですが、いまいち理解が及びません。お時間のある時で結構ですので、ご教授いただけないでしょうか。 ①RecordManage.java(1)において、@Componentを記載することnewせずともRecordManageというインスタンスが生成されるという理解で合っておりますでしょうか。 ②RecordManage.java(3)において、コンストラクタインジェクションにする意図。jdbcTemplateを動的に注入して・・・ということだと考えていますが、コンストラクタインジェクションを行わない場合、どのようなことが起こりえるのでしょうか。(テストのしやすさとかの問題だけ?) ③AddressBookController.java(2)において、コンストラクタを追加していますがこれはRecordManage.java(3)で作成したコンストラクタを受け取るためのものという理解で合っておりますでしょうか。
usako

2019/06/04 01:25 編集

rubytomato様、丁寧な説明、本当に感謝です。 回答を咀嚼するのに時間がかかりお礼が遅くなりました。 > ③AddressBookController.java(2)において、コンストラクタを追加して >いますがこれはRecordManage.java(3)で作成したコンストラクタを受け >取るためのものという理解で合っておりますでしょうか。 とんちんかんな質問で失礼しました(汗)質問の意図としては、jdbcTemplateがRecordManagerクラスに注入され、更にrecordManagerがAddressBookControllerクラスに注入されるという具合に値(オブジェクト?)が引き継がれていくのでしょうか、ということでした。 (この質問の仕方も???だったら申訳ないです) あと、基本的なことかもしれませんが、コンストラクラインジェクションと普通の引数ありのコンストラクタの見極めはどのように行うのでしょうか。(記述方法としては同じになると思うのですが・・・) またこの場合、デフォルトコンストラクタが見当たらないのもなぜなのかわかりません。これもSpringが勝手にやってくれているということなのでしょうか。
usako

2019/06/05 04:52 編集

rubytomato様、何度も返信してくださってありがとうございます。 お陰でコンストラクタインジェクションのことが少し理解できたような気がします。(自身で一から書けるようになるのはまだ先のことかもしれませんが・・・) まずはソースを読めるように精進したいと思っております。 本当にありがとうございました。 ↓とんちんかんな質問して申訳ありませんでした・・・ >デフォルトコンストラクタが見当たらないのもなぜなのかわかりません。 >これもSpringが勝手にやってくれているということなのでしょうか。
guest

0

上記の回答ですが、自分は、@Controller 以外から
呼び出すには、@Service を経由する必要があると理解しました。

提示されたソースでは、@Service の文字は存在していないので、
サービス経由で使用していないのではと思いました。

投稿2019/05/29 04:42

kamikaze.cappa

総合スコア558

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

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

usako

2019/05/29 05:18 編集

アドバイスありがとうございます。kamimaze.cappa様のご指摘もあり、 AddressBookController.javaとRecordManager.javaを@Serviceを使って以下のように修正してみましたが、やはりNullPointerExceptionが起きてしまいます。記述が悪いのでしょうか。 ↓----------------------------------------------- package jp.practice.address; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping(value = "/book") public class AddressBookController { private static final String INIT = "init"; private static final String REFER = "refer"; private static final String UPDATE = "update"; private static final String LIST = "list"; private static final String INIMSG = "従業員番号を入力してください"; private static final String REFMSG = "情報が取得できました"; private static final String UPDMSG = "情報を更新してください"; private static final String ERRMSG = "該当するデータはありません"; @RequestMapping(value = "/start") public String init(AddressBookForm form, Model model) { model.addAttribute("message", INIMSG); return INIT; } -----割愛----- @RequestMapping(params = "list") public String list(Model model) { //*start *** List<Map<String, Object>> employeeList = service.getEmployeeList(); // List<Map<String, Object>> employeeList = RecordManager.getEmployeeList(); //*e n d model.addAttribute("employeeList", employeeList); model.addAttribute("employeeCount", employeeList.size()); return LIST; } //*start *** @Autowired RecordManager service; //*e n d } ↓ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー package jp.practice.address; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; /**start ****/ @Service /**e n d*/ public class RecordManager { @Autowired private static JdbcTemplate jdbcTemplate; -----割愛------- public static List<Map<String, Object>> getEmployeeList() { if (jdbcTemplate == null) { System.out.println("jdbcTemplate is null"); } List<Map<String, Object>> list1 = jdbcTemplate.queryForList("select * from unit02.addressbook order by id"); return list1; }
guest

0

https://teratail.com/questions/68121

上記が参考になると思います。

投稿2019/05/29 04:05

kamikaze.cappa

総合スコア558

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

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

usako

2019/05/29 05:19 編集

アドバイスありがとうございます。 この記事も調べていて同じようにしてみたつもりなのですが、エラーが解除されませんでした。 具体的には、AddressBookController.javaとRecordManager.javaを@Serviceを使って以下のように修正してみましたが、やはりNullPointerExceptionが起きてしまいます。記述が悪いのでしょうか。 ↓----------------------------------------------- package jp.practice.address; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping(value = "/book") public class AddressBookController { private static final String INIT = "init"; private static final String REFER = "refer"; private static final String UPDATE = "update"; private static final String LIST = "list"; private static final String INIMSG = "従業員番号を入力してください"; private static final String REFMSG = "情報が取得できました"; private static final String UPDMSG = "情報を更新してください"; private static final String ERRMSG = "該当するデータはありません"; @RequestMapping(value = "/start") public String init(AddressBookForm form, Model model) { model.addAttribute("message", INIMSG); return INIT; } -----割愛----- @RequestMapping(params = "list") public String list(Model model) { //*start *** List<Map<String, Object>> employeeList = service.getEmployeeList(); // List<Map<String, Object>> employeeList = RecordManager.getEmployeeList(); //*e n d model.addAttribute("employeeList", employeeList); model.addAttribute("employeeCount", employeeList.size()); return LIST; } //*start *** @Autowired RecordManager service; //*e n d } ↓ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー package jp.practice.address; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; /**start ****/ @Service /**e n d*/ public class RecordManager { @Autowired private static JdbcTemplate jdbcTemplate; -----割愛------- public static List<Map<String, Object>> getEmployeeList() { if (jdbcTemplate == null) { System.out.println("jdbcTemplate is null"); } List<Map<String, Object>> list1 = jdbcTemplate.queryForList("select * from unit02.addressbook order by id"); return list1; }
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問