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

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

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

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

Java

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

Q&A

解決済

2回答

23379閲覧

DB検索をしてヒットしない場合の判定方法がわかりません。

usako

総合スコア31

JDBC

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

Java

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

0グッド

0クリップ

投稿2019/05/31 08:23

編集2019/05/31 13:23

前提・実現したいこと

閲覧いただき、ありがとうございます。
Eclipse,Springを使ってJAVAの勉強をしている(超)初心者です。
元々、受講していた通信教育の課題がDBを使用しておらず、
内部にテーブルを保持している構造だったので、それを
MySQL,JDBCで外部化しようとしています。
一覧表示、更新、参照機能だけのシンプルな画面です。
現在、参照機能で該当データを検索するところまでは動作するよう
になったのですが、わざと存在しないIDを入力すると
以下のエラーが発生してしまいます。
意味は「1件データが返ってくるはずなのに、1件もデータが
返ってこない」といったようなことだと理解しています。
rowNumに該当する件数が入ってくるのではと考えて
以下のようなコードを書いてみたのですが(★部分)、
その前で落ちてしまいます。
どうすべきなのか、何を調べればよいのかなど、
どなたかご教示いただけないでしょうか。

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

HTTPステータス 500 - Request processing failed; nested exception is org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0 type 例外レポート メッセージ Request processing failed; nested exception is org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0 説明 The server encountered an internal error that prevented it from fulfilling this request. 例外 org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982) org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) javax.servlet.http.HttpServlet.service(HttpServlet.java:643) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) javax.servlet.http.HttpServlet.service(HttpServlet.java:723) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 原因 org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0 org.springframework.dao.support.DataAccessUtils.requiredSingleResult(DataAccessUtils.java:71) org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:795) jp.practice.address.RecordManager.selectEmployee(RecordManager.java:57) jp.practice.address.AddressBookController.refer(AddressBookController.java:38) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:498) org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) javax.servlet.http.HttpServlet.service(HttpServlet.java:643) org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) javax.servlet.http.HttpServlet.service(HttpServlet.java:723) org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)

該当のソースコード

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 10@Controller 11@RequestMapping(value = "/book") 12public class AddressBookController { 13 private static final String INIT = "init"; 14 private static final String REFER = "refer"; 15 private static final String UPDATE = "update"; 16 private static final String LIST = "list"; 17 private static final String INIMSG = "従業員番号を入力してください"; 18 private static final String REFMSG = "情報が取得できました"; 19 private static final String UPDMSG = "情報を更新してください"; 20 private static final String ERRMSG = "該当するデータはありません"; 21 22 private RecordManager recordManager; 23 public AddressBookController(RecordManager recordManager) { 24 this.recordManager = recordManager; 25 } 26 27 @RequestMapping(value = "/start") 28 public String init(AddressBookForm form, Model model) { 29 model.addAttribute("message", INIMSG); 30 return INIT; 31 } 32 33 @RequestMapping(params = "reference") 34 public String refer(AddressBookForm form, Model model) { 35 Employee employee = recordManager.selectEmployee(form.getId()); 36 if (employee != null) { 37 form.setName(employee.getName()); 38 form.setPhone(employee.getPhone()); 39 form.setAddress(employee.getAddress()); 40 model.addAttribute("message", REFMSG); 41 return REFER; 42 } else { 43 model.addAttribute("message", ERRMSG); 44 return INIT; 45 } 46 } 47 48 @RequestMapping(params = "toInit") 49 public String toInit(AddressBookForm form, Model model) { 50 model.addAttribute("message", INIMSG); 51 return INIT; 52 } 53 54 @RequestMapping(params = "update") 55 public String update(AddressBookForm form, Model model) { 56 Employee employee = recordManager.selectEmployee(form.getId()); 57 if (employee != null) { 58 form.setName(employee.getName()); 59 form.setPhone(employee.getPhone()); 60 form.setAddress(employee.getAddress()); 61 model.addAttribute("message", UPDMSG); 62 return UPDATE; 63 } else { 64 model.addAttribute("message", ERRMSG); 65 return INIT; 66 } 67 } 68 69 @RequestMapping(params = "reflection") 70 public String reflection(AddressBookForm form, Model model) { 71 Employee employee = new Employee(form.getId(), form.getName(), form.getPhone(), form.getAddress()); 72 RecordManager.updateEmployee(employee); 73 model.addAttribute("message", INIMSG); 74 return INIT; 75 } 76 77 @RequestMapping(params = "list") 78 public String list(Model model) { 79 List<Map<String, Object>> employeeList = recordManager.getEmployeeList(); 80 model.addAttribute("employeeList", employeeList); 81 model.addAttribute("employeeCount", employeeList.size()); 82 return LIST; 83 } 84 85}

java

1package jp.practice.address; 2 3import java.sql.ResultSet; 4import java.sql.SQLException; 5import java.util.List; 6import java.util.Map; 7 8import org.springframework.jdbc.core.JdbcTemplate; 9import org.springframework.jdbc.core.RowMapper; 10import org.springframework.stereotype.Component; 11@Component 12public class RecordManager { 13 private JdbcTemplate jdbcTemplate; 14 15 public RecordManager(JdbcTemplate jdbcTemplate) { 16 this.jdbcTemplate = jdbcTemplate; 17 } 18 19 /** 20 * 指定したID のレコードを取得 21 * 22 * @param id 23 * 従業員番号 24 * @return Employee 25 */ 26 27 * @param name ****/ 28 public Employee selectEmployee(String id) { 29 return jdbcTemplate.queryForObject("select * from unit02.addressbook where id = ? ", 30 new Object[]{ id }, 31 new RowMapper<Employee>() { 32 @Override 33 public Employee mapRow(ResultSet rs, int rowNum) throws SQLException { 34if (rowNum == 0){ 35return null; 36} 37 Employee employee = new Employee("","","",""); 38 employee.setId(rs.getString("id")); 39 employee.setName(rs.getString("name")); 40 employee.setPhone(rs.getString("tel")); 41 employee.setAddress(rs.getString("address")); 42 return employee; 43 } 44 }); 45 } 46 47 /** 48 * 指定した従業員情報を反映 49 * 50 * @param emp 51 * 従業員情報 52 */ 53 public static void updateEmployee(Employee emp) { 54// int index = list.indexOf(emp); 55// list.set(index, emp); 56 } 57 58 public List<Map<String, Object>> getEmployeeList() { 59 List<Map<String, Object>> list = jdbcTemplate.queryForList("select * from unit02.addressbook order by id"); 60 return list; 61 } 62}

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2019/05/31 10:16

同じ全文で始める質問ならまず書籍を購入するか別の通信講座を受けてください。
m.ts10806

2019/05/31 10:24

エラーもコードブロック対応してもらえたらと。平で提示されてもかなり見づらいので…
usako

2019/06/03 04:04 編集

ご指摘ありがとうございます。 コードブロックで未対応の件、申し訳ないです。お作法を心得ておりませんでした。 次回から留意するようにします。
guest

回答2

0

ベストアンサー

原因
org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0

とありますので,

意味は「1件データが返ってくるはずなのに、1件もデータが返ってこない」といったようなことだと理解しています

で合っていると思います.
では EmptyResultDataAccessException はどこで発生しているかと言いますと,

jp.practice.address.RecordManager.selectEmployee(RecordManager.java:57)

ですから, 対処箇所も合っていると思います.
ですが,

rowNumに該当する件数が入ってくるのではと考えて以下のようなコードを書いてみた

ここは推測するのでは無く, メソッドの仕様をご確認するべきかと思います.

バージョンが新しいか古いかが分かりませんが, 見つけた所では
JdbcTemplate (Spring Framework 5.1.7.RELEASE API)

queryForObject
@Nullable
public <T> T queryForObject(String sql,
@Nullable
Object[] args,
RowMapper<T> rowMapper)
throws DataAccessException

rowMapper - a callback that will map one object per row

Throws:
IncorrectResultSizeDataAccessException - if the query does not return exactly one row

とあり, rowMapper( の mapRow メソッド)は per row=行毎 に呼ばれますので, 行が無かった場合は呼ばれなさそうです.
ついでに, mapRow のパラメータ rowNum は
RowMapper (Spring Framework 5.1.7.RELEASE API)

mapRow
@Nullable
T mapRow(ResultSet rs,
int rowNum)
throws SQLException

Parameters:

rowNum - the number of the current row

今が何行目なのかを伝えてくるだけですので 0 はありえません.

対処方ですが, return を try-catch で囲み IncorrectResultSizeDataAccessException( queryForObject の throws に書かれている, EmptyResultDataAccessException のスーパークラスです) をキャッチしたら null を return する方法が一つです.

もう一つは, 同じパラメータで List を返すことの出来る

query
public <T> List<T> query(String sql,
@Nullable
Object[] args,
RowMapper<T> rowMapper)
throws DataAccessException

を使うという方法です.
結果を即 return せず, 一度 List<Employee> の変数で受け取り, size() が 0 なら null を return, 1なら変数から取り出した Employee を return すれば良いかと思います.

投稿2019/05/31 10:34

編集2019/05/31 10:43
jimbe

総合スコア13095

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

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

usako

2019/06/03 04:13

jimbe様、コメントありがとうございます。 ご教授いただいたようにtry-catch文でIncorrectResultSizeDataAccessExceptionを拾うようにしたらうまく動くようになりました! まだまだ勉強不足なのでこれからもがんばりたいと思います。
guest

0

例外にはすべて意味があります。

今回の場合

EmptyResultDataAccessException

が投げられているのであーる。

空で(empty)
返却されたデータ(ResultData)
を操作(Access)
したので例外にします(Exception)

という感じ

投稿2019/05/31 10:20

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

usako

2019/06/03 04:11

asahina1979様、ご教授ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.39%

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

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

質問する

関連した質問