riku__02
@riku__02

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Spring bootにてMy Batisを利用しupdate・delete処理作成中の質問

解決したいこと

Spring解体新書という書籍で8章部分を実施中です。
エラーなくコーディング自体はできているのですが、ユーザ詳細画面より、削除ボタンを押しても、ユーザ一覧にリダイレクトされるだけで、ユーザが削除されない。
更新ボタンを押しても、ユーザ一覧にリダイレクトさえされず何も起こらないという状態です。。
(動作が期待通りの動きではない。)

本来であれば、更新ボタン押下で、ユーザ一覧画面に遷移&情報更新
削除ボタンでユーザ一覧画面より該当のユーザが削除されていることを実践したいです。
恐らくSQL関連が問題ではないだろうかと思っていますが、エラーではないのでどこを見れば良いか検討がつかず、改善策が見つかっていません。。可能でしたら気になる点をご指摘、アドバイスお願いいたします。。

発生している問題・エラー

■削除ボタン押下時のログ

2024-10-15T23:51:33.106+09:00[0;39m [32mDEBUG[0;39m [35m12856[0;39m [2m---[0;39m [2m[SpringBootSample] [nio-8080-exec-1][0;39m [2m[0;39m[36mc.e.d.repository.UserMapper.deleteOne   [0;39m [2m:[0;39m ==>  Preparing: delete from m_user where user_Id = ?
[2m2024-10-15T23:51:33.108+09:00[0;39m [32mDEBUG[0;39m [35m12856[0;39m [2m---[0;39m [2m[SpringBootSample] [nio-8080-exec-1][0;39m [2m[0;39m[36mc.e.d.repository.UserMapper.deleteOne   [0;39m [2m:[0;39m ==> Parameters: (String)
[2m2024-10-15T23:51:33.118+09:00[0;39m [32mDEBUG[0;39m [35m12856[0;39m [2m---[0;39m [2m[SpringBootSample] [nio-8080-exec-1][0;39m [2m[0;39m[36mc.e.d.repository.UserMapper.deleteOne   [0;39m [2m:[0;39m <==    Updates: 0
[2m2024-10-15T23:51:33.149+09:00[0;39m [32mDEBUG[0;39m [35m12856[0;39m [2m---[0;39m [2m[SpringBootSample] [nio-8080-exec-8][0;39m [2m[0;39m[36mc.e.demo.repository.UserMapper.findMany [0;39m [2m:[0;39m ==>  Preparing: select user_id as userId ,password ,user_name as userName ,birthday ,age ,gender ,department_id as departmentId ,role from m_user
[2m2024-10-15T23:51:33.150+09:00[0;39m [32mDEBUG[0;39m [35m12856[0;39m [2m---[0;39m [2m[SpringBootSample] [nio-8080-exec-8][0;39m [2m[0;39m[36mc.e.demo.repository.UserMapper.findMany [0;39m [2m:[0;39m ==> Parameters: 
[2m2024-10-15T23:51:33.346+09:00[0;39m [32mDEBUG[0;39m [35m12856[0;39m [2m---[0;39m [2m[SpringBootSample] [nio-8080-exec-8][0;39m [2m[0;39m[36mc.e.demo.repository.UserMapper.findMany [0;39m [2m:[0;39m <==      Total: 2

■更新ボタン押下時のログ
ボタンを押してもログも出ません。

※現在の画面
image.png

該当するソースコード

■UserMapper.java

package com.example.demo.repository;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import com.example.demo.domain.user.model.MUser;

@Mapper
public interface UserMapper {
	/**ユーザー登録*/
	public int insertOne(MUser user);
	
	/** ユーザー取得*/
	public List<MUser> findMany();
	
	/**ユーザー取得(1件) */
	public MUser findOne(String userId);
	
	/** ユーザー更新(1件)*/
	public void updateOne(@Param("userId") String userId,
	@Param("password") String password,
	@Param("userName") String userName);
	
	/**ユーザー削除(1件) */
	public int deleteOne(@Param("userId") String userId);
}

■UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- Mapperとxmlのマッピング -->
<mapper namespace="com.example.demo.repository.UserMapper">

	<!-- マッピング定義ユーザー -->
	<resultMap type="com.example.demo.domain.user.model.MUser" id="user">
		<id column="user_id" property="userId" />
		<result column="password" property="password" />
		<result column="user_name" property="userName" />
		<result column="birthday" property="birthday" />
		<result column="age" property="age" />
		<result column="gender" property="gender" />
		<result column="department_id" property="departmentId" />
		<result column="role" property="role" />
	</resultMap>

	<!-- ユーザー1件登録 -->
	<insert id="insertOne">
		insert into m_user(
		user_id
		,password
		,user_name
		,birthday
		,age
		,gender
		,department_id
		,role
		)
		values (
		#{userId}
		,#{password}
		,#{userName}
		,#{birthday}
		,#{age}
		,#{gender}
		,#{departmentId}
		,#{role}
		)
</insert>

	<!-- ユーザー複数件取得 -->
	<select id="findMany" resultType="com.example.demo.domain.user.model.MUser">
		select
		user_id as userId
		,password
		,user_name as userName
		,birthday
		,age
		,gender
		,department_id as departmentId
		,role
		from
		m_user
	</select>

	<!-- ユーザー1件検索 -->
	<select id="findOne" resultMap="user">
		select
		user_id as userId
		,password
		,user_name as userName
		,birthday
		,age
		,gender
		,department_id as departmentId
		,role
		from
		m_user
		where
		user_id =#{userId}
	</select>

	<!-- ユーザー1件更新 -->
	<update id="updateOne">
		update
		 m_user
		set
		 password = #{password}
		 ,user_Name = #{userName}
		where
		 user_Id = #{userId}
	</update>

	<!-- ユーザー1件削除 -->
	<delete id="deleteOne">
		delete from
		 m_user
		where
		 user_Id = #{userId}
</delete>
</mapper>

■UserService.java

package com.example.demo.domain.user.service;

import java.util.List;

import com.example.demo.domain.user.model.MUser;

public interface UserService {
	/*ユーザー登録*/
	public void signup(MUser user);
    /** ユーザー取得 */
    public List<MUser> getUsers();
    /** ユーザ取得(1件)*/
    public MUser getUserOne(String userId);
    /** ユーザー更新(1件)*/
    public void updateUserOne(String userId,String password, String userName);
    /** ユーザー削除(1件)*/
    public void deleteUserOne(String userId);
}

■UserServiceImpl.java

package com.example.demo.domain.user.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.demo.domain.user.model.MUser;
import com.example.demo.domain.user.service.UserService;
import com.example.demo.repository.UserMapper;

@Service
public class UserServiceImpl implements UserService {
	@Autowired
	private UserMapper mapper;

	/*ユーザ登録*/
	@Override
	public void signup(MUser user) {
		user.setDepartmentId(1); //部署
		user.setRole("ROLE_GENERAL");
		mapper.insertOne(user);
	}

	/** ユーザー取得 */
	@Override
	public List<MUser> getUsers() {
		return mapper.findMany();
	}

	/** ユーザー取得(1件)*/
	@Override
	public MUser getUserOne(String userId) {
		return mapper.findOne(userId);
	}

	/** ユーザー更新(1件) */
	@Override
	public void updateUserOne(String userId, String password, String userName) {
		// TODO 自動生成されたメソッド・スタブ
		mapper.updateOne(userId, password, userName);
	}

	/** ユーザー削除(1件) */
	@Override
	public void deleteUserOne(String userId) {
		// TODO 自動生成されたメソッド・スタブ
		mapper.deleteOne(userId);
	}
}

■UserDetailController.java

package com.example.demo.controller;

import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.example.demo.domain.user.model.MUser;
import com.example.demo.domain.user.service.UserService;
import com.example.demo.form.UserDetailForm;

@Controller
@RequestMapping("/user")
public class UserDetailController {

    @Autowired
    private UserService userService;

    @Autowired
    private ModelMapper modelMapper;

    /** ユーザー詳細画面を表示 */
    @GetMapping("/detail/{userId:.+}")
    public String getUser(UserDetailForm form, Model model, @PathVariable("userId") String userId) {

        // ユーザーを1件取得
        MUser user = userService.getUserOne(userId);
        user.setPassword(null);

        // MUserをformに変換
        form = modelMapper.map(user, UserDetailForm.class);

        // Modelに登録
        model.addAttribute("userDetailForm", form);

        // ユーザー詳細画面を表示
        return "user/detail";
    }
    
    /** ユーザー更新処理 */
    @PostMapping(value ="/detail", params = "update")
    public String updateUser(UserDetailForm form, Model model) {
    	
    	//ユーザーを更新
    	userService.updateUserOne(form.getUserId(),form.getPassword(), form.getUserName());
    	
    	//ユーザー一覧画面にリダイレクト
    	return "redirect:/user/list";
    }
    
    /** ユーザー削除処理*/
    @PostMapping(value = "/detail", params="delete")
    public String deleteUser(UserDetailForm form, Model model ) {
    	
    	//ユーザーを削除
    	userService.deleteUserOne(form.getUserId());
    	
    	//ユーザー一覧画面にリダイレクト
    	return "redirect:/user/list";
    }
}

自分で試したこと

今実施しているupdate,delete処理における改修ソースはこれらになります。
もう少し自分でも見直しますが、ここじゃない?など指摘ありましたらよろしくお願いいたします。

※サンプルソースと全ファイルウィンマージにて比較し、合致していること確認できています。
益々、原因がわかっていません、、

0

2Answer

	<!-- ユーザー1件更新 -->
	<update id="updateOne">
		update
		 m_user
		set
		 password = #{password}
		 ,user_Name = #{userName}
		where
		 user_Id = #{userId}
	</update>

	<!-- ユーザー1件削除 -->
	<delete id="deleteOne">
		delete from
		 m_user
		where
		 user_Id = #{userId}
</delete>

user_Idではなく、user_idではないでしょうか。(insertやselectのクエリを見た限り)

0Like

Comments

  1. @riku__02

    Questioner

    @eno49conanさん
    こんばんは!ご指摘の通りuser_Idではなく、user_idでしたので、この点は修正いたしました。ありがとうございます。
    しかし、起こっている事象は解決していないといった状態です、、

※サンプルソースと全ファイルウィンマージにて比較し、合致していること確認できています。

サンプルソースは期待通りの動作をしているのでしょうか?
そうであれば何か比較が漏れているファイルがあるのだと思います。
なお user_Nameuser_name の誤りかと思います。

	<update id="updateOne">
		update
		 m_user
		set
		 password = #{password}
-		 ,user_Name = #{userName}
+		 ,user_name = #{userName}
		where
-		 user_Id = #{userId}
+		 user_id = #{userId}
	</update>

また、ユーザー詳細画面で ユーザーID・パスワード・ユーザー名 が表示されていませんが単純に更新・削除ボタンの押下時にそれらの情報を渡せていないということはあったりしませんか?
UserDetailControllerupdateUser, deleteUser メソッド内で form の値は期待通りになっているか、デバッグモードやログへの出力などで確認してみてください。

0Like

Comments

  1. @riku__02

    Questioner

    @dorankoさんこんばんは!
    ご回答頂きありがとうございます。。
    サンプルソースはソース比較にしか使用しておらず、プロジェクトとして配置し、起動して動きを見ることはしていませんでした。ありがとうございます。。。
    サンプルソースで動かしてみたところ正常な動き(更新、削除)であったのでご指摘の通り、比較漏れしていそうです。
    確かにユーザ一覧画面では以下のキャプチャの通り、値があるのですが、詳細画面にいくと表示されていませんでした。
    UserDetailController を見直してみようと思います。
    本当にありがとうございます。
    image.png

    追記))
    ■UserDetailController.javaの以下部分でuserのuserName,userIdがnullでセットしてありました。。一旦ここを遡っていますが、時間がかかっています。。

     // ユーザーを1件取得
            MUser user = userService.getUserOne(userId);
            user.setPassword(null);
    
  2. @riku__02 さん
    詳細画面で値が表示されていないことについては 1 件のユーザー情報を取得する際に userId と userName (と departmentId も) が以下のマッピング定義の部分の影響で取得できていないように見えます。
    マッピング定義についてもう一度見直してみると良いかもしれません。

    	<!-- マッピング定義(ユーザー) -->
    	<resultMap type="com.example.demo.domain.user.model.MUser" id="user">
    		<id column="user_id" property="userId" />
    		<result column="password" property="password" />
    		<result column="user_name" property="userName" />
    〜略〜
    	<!-- ユーザー1件検索 -->
    	<select id="findOne" resultMap="user">
    		select
    		user_id as userId
    		,password
    		,user_name as userName
    

    password については取得結果を java 側で null に上書きしちゃってますね (おそらく画面にパスワードが平文で表示されないようにという意図なのでしょう)。

  3. @riku__02

    Questioner

    @dorankoさん
    色々とアドバイス頂きありがとうございました。
    doranekoさんのアドバイスからどこが取れていないや、問題点あぶり出すことが出来、無事改修できました。。

    ■UserMapper.xmlの以下部分(selectの内容)を修正することで、userId と userNameを取得するようになり、更新、削除も成功しました。
    as句で別名つけて個々にセレクトしようとしていたのが駄目であったのですかね、、

    ・旧

    	<!-- ユーザー1件検索 -->
    	<select id="findOne" resultMap="user">
    		select
    		user_id as userId
    		,password
    		,user_name as userName
    		,birthday
    		,age
    		,gender
    		,department_id as departmentId
    		,role
    		from
    		m_user
    		where
    		user_id =#{userId}
    	</select>
    

    新(修正後)

    	<!-- ユーザー1件検索 -->
    	<select id="findOne" resultMap="user">
    		select
            *
    		from
    		m_user
    		where
    		user_id =#{userId}
    	</select>
    
  4. @riku__02 さん
    改修できたようで何よりです。

    as句で別名つけて個々にセレクトしようとしていたのが駄目であったのですかね、、

    というよりはマッピング定義の <id column="user_id" property="userId" /> でカラム名 user_id の値を MUser の userId に対応させているのに、修正前の SQL では user_id ではなく userId として取得してしまっているからですね。
    SQL の結果をどのように Java のクラスに対応づけているかについて、xml の記述を復習されると理解に役立つかと思います。

  5. @riku__02

    Questioner

    @dorankoさん
    解説頂きありがとうございます。
    SQLとJavaクラスの対応づけ、xmlの記述等まだ理解が未熟ですのでしっかり復習を行おうと思います。またご指摘頂いた以下の内容で確かに、、となりました。

    [というよりはマッピング定義の でカラム名 user_id の値を MUser の userId に対応させているのに、修正前の SQL では user_id ではなく userId として取得してしまっているからですね。]

    これに関して対応づけが理解できていなかったためであり、勉強になりました。
    SQLでas userIdとしていたら紐付かないです。。
    gitとqiitaに記録し、先に進もうと思います!遅くまでご対応頂き誠にありがとうございました。。

Your answer might help someone💌