5
2

More than 3 years have passed since last update.

【Java・SpringBoot】Spring JDBC / RowMapper(SpringBootアプリケーション実践編15)

Posted at

ホーム画面からユーザー一覧画面に遷移し、ユーザーの詳細を表示するアプリケーションを作成して、Spring JDBCの使い方について学びます⭐️
前回までで、Jdbc Templateを使った基本のCRUD操作について学びました
今回は応用編で、RowMapperを学びます^^
構成は前回の記事を参考にしてください

⭐️前回の記事
【Java・SpringBoot】Spring JDBC でユーザー削除処理(SpringBootアプリケーション実践編14)

RowMapper

  • RowMapperとは、データベースのレコード(行)と、Javaオブジェクトのマッピングを行うためのクラス
  • これまでは、Userテーブルのデータを1件取得するには、
    select文で取得した結果をMapから取り出して、Userクラスのインスタンスにセットしていた
    • 似たようなselect文を沢山作ると、コードの可読性が下がる。。
  • →そんな時に、RowMapper!

UserRowMapper作成

  • まずは、UserRowMapperを作成

RowMapperの使いかた

  • RowMapper<?>インターフェースを継承(implements)
    • ?=マッピングに使うJavaオブジェクトのクラスを指定
    • RowMapperを継承して、mapRowメソッドをOverride
    • public class UserRowMapper implements RowMapper<User> {
    • 引数のResultSetにはSelect結果が入る
      • 以下ではResultSetの値をUserクラスにセット
      • 最後にUserクラスのインスタンスをreturn
  • →RowMapperではSelect結果とUserクラスを、あらかじめマッピングできる
UserRowMapper.java
package com.example.demo.login.domain.repository.jdbc;

import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
import com.example.demo.login.domain.model.User;

public class UserRowMapper implements RowMapper<User> {

    @Override
    public User mapRow(ResultSet rs, int rowNum) throws SQLException {

        //戻り値用のUserインスタンスを生成
        User user = new User();
        //ResultSetの取得結果をUserインスタンスにセット
        user.setUserId(rs.getString("user_id"));
        user.setPassword(rs.getString("password"));
        user.setUserName(rs.getString("user_name"));
        user.setBirthday(rs.getDate("birthday"));
        user.setAge(rs.getInt("age"));
        user.setMarriage(rs.getBoolean("marriage"));
        user.setRole(rs.getString("role"));

        return user;
    }
}

UserDaoJdbcImpl継承クラス作成

  • select文を実行する箇所だけRowMapperに変えて、insert、update文はUserDaoJdbcImplと同じ動きをする
  • 以下の例では、JdbcTemplateのメソッドの引数に、RowMapperをセット
  • select結果が入ったUserクラスやList<User>の結果が返る
UserDaoJdbcImpl2.java
package com.example.demo.login.domain.repository.jdbc;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.example.demo.login.domain.model.User;

@Repository("UserDaoJdbcImpl2")
public class UserDaoJdbcImpl2 extends UserDaoJdbcImpl {

    @Autowired
    private JdbcTemplate jdbc;

    //ユーザー1件取得
    @Override
    public User selectOne(String userId) {
        //1件取得用SQL
        String sql = "SELECT * FROM m_user WHERE user_id = ?";
        //RowMapperの生成
        UserRowMapper rowMapper = new UserRowMapper();
        //SQL実行
        return jdbc.queryForObject(sql, rowMapper, userId);
    }

    //ユーザー全件取得
    @Override
    public List<User> selectMany() {
        //M_USERテーブルのデータを全件取得するSQL
        String sql = "SELECT * FROM m_user";
        //RowMapperの生成
        RowMapper<User> rowMapper = new UserRowMapper();
        //SQL実行
        return jdbc.query(sql, rowMapper);
    }
}

@Repositoryアノテーション引数を追加

  • UserDaoJdbcImpl.java@Repositoryアノテーションに引数を追加し、Bean名をセット
  • →Bean名をセットすることで、@Autowiredする際に、どのクラスを使用するか指定できる!(次にサービスクラスを修正してBean指定する)
  • コード全文は下記参考
UserDaoJdbcImpl.java
//中略
@Repository("UserDaoJdbcImpl")
public class UserDaoJdbcImpl implements UserDao {
//中略

サービスクラスを修正

@Qualifier

  • @Autowired@Qualifierアノテーションを使用すると、どのBeanを使用するか指定できる
    • UserDaoインターフェースを継承したクラスが1つの場合は、Springが自動でBeanを探してくれる
    • インターフェースを継承したクラスが2つ(UserDaoJdbcImpl/UserDaoJdbcImpl2)の場合は、@Qualifierが必要
    • Springではインターフェースを作り、それを継承したクラスを作るというのが一般的な使い方
  • コード全文は下記参考
UserService.java
//中略
@Service
public class UserService {
    @Autowired
    @Qualifier("UserDaoJdbcImpl2")
    UserDao dao;
//中略

SpringBootを起動してホーム画面確認!

  • http://localhost:8080/home
  • ユーザー一覧、ユーザー詳細画面に移ると、コンソールの表示がUserDaoJdbcImpl2に変わっています
  • これでRowMapperを使うことができました〜^o^
//コンソール画面
メソッド開始: String com.example.demo.login.controller.HomeController.getUserDetail(SignupForm,Model,String)
userId = nekomofu@xxx.co.jp
メソッド開始: User com.example.demo.login.domain.repository.jdbc.UserDaoJdbcImpl2.selectOne(String)
メソッド終了: User com.example.demo.login.domain.repository.jdbc.UserDaoJdbcImpl2.selectOne(String)
メソッド終了: String com.example.demo.login.controller.HomeController.getUserDetail(SignupForm,Model,String)

(参考)コード全文

UserDaoJdbcImpl.java
package com.example.demo.login.domain.repository.jdbc;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import com.example.demo.login.domain.model.User;
import com.example.demo.login.domain.repository.UserDao;

@Repository("UserDaoJdbcImpl")
public class UserDaoJdbcImpl implements UserDao {

    @Autowired
    JdbcTemplate jdbc;

    // Userテーブルの件数を取得.
    @Override
    public int count() throws DataAccessException {

        //全件取得してカウント
        int count = jdbc.queryForObject("SELECT COUNT(*) FROM m_user", Integer.class);

        return count;
    }

    // Userテーブルにデータを1件insert.
    @Override
    public int insertOne(User user) throws DataAccessException {

        //1件登録
        int rowNumber = jdbc.update("INSERT INTO m_user(user_id,"
                + " password,"
                + " user_name,"
                + " birthday,"
                + " age,"
                + " marriage,"
                + " role)"
                + " VALUES(?, ?, ?, ?, ?, ?, ?)",
                user.getUserId(),
                user.getPassword(),
                user.getUserName(),
                user.getBirthday(),
                user.getAge(),
                user.isMarriage(),
                user.getRole());

        return rowNumber;
    }

    // Userテーブルのデータを1件取得
    @Override
    public User selectOne(String userId) throws DataAccessException {

        // 1件取得
        Map<String, Object> map = jdbc.queryForMap("SELECT * FROM m_user"
                + " WHERE user_id = ?", userId);

        // 結果返却用の変数
        User user = new User();

        // 取得したデータを結果返却用の変数にセットしていく
        user.setUserId((String) map.get("user_id")); //ユーザーID
        user.setPassword((String) map.get("password")); //パスワード
        user.setUserName((String) map.get("user_name")); //ユーザー名
        user.setBirthday((Date) map.get("birthday")); //誕生日
        user.setAge((Integer) map.get("age")); //年齢
        user.setMarriage((Boolean) map.get("marriage")); //結婚ステータス
        user.setRole((String) map.get("role")); //ロール

        return user;
    }

    // Userテーブルの全データを取得.
    @Override
    public List<User> selectMany() throws DataAccessException {

        // M_USERテーブルのデータを全件取得
        List<Map<String, Object>> getList = jdbc.queryForList("SELECT * FROM m_user");

        // 結果返却用の変数
        List<User> userList = new ArrayList<>();

        // 取得したデータを結果返却用のListに格納していく
        for (Map<String, Object> map : getList) {

            //Userインスタンスの生成
            User user = new User();

            // Userインスタンスに取得したデータをセットする
            user.setUserId((String) map.get("user_id")); //ユーザーID
            user.setPassword((String) map.get("password")); //パスワード
            user.setUserName((String) map.get("user_name")); //ユーザー名
            user.setBirthday((Date) map.get("birthday")); //誕生日
            user.setAge((Integer) map.get("age")); //年齢
            user.setMarriage((Boolean) map.get("marriage")); //結婚ステータス
            user.setRole((String) map.get("role")); //ロール

            //結果返却用のListに追加
            userList.add(user);
        }

        return userList;
    }

    // Userテーブルを1件更新.
    @Override
    public int updateOne(User user) throws DataAccessException {

        //1件更新
        int rowNumber = jdbc.update("UPDATE M_USER"
                + " SET"
                + " password = ?,"
                + " user_name = ?,"
                + " birthday = ?,"
                + " age = ?,"
                + " marriage = ?"
                + " WHERE user_id = ?",
                user.getPassword(),
                user.getUserName(),
                user.getBirthday(),
                user.getAge(),
                user.isMarriage(),
                user.getUserId());
    }

    // Userテーブルを1件削除.
    @Override
    public int deleteOne(String userId) throws DataAccessException {

        //1件削除
        int rowNumber = jdbc.update("DELETE FROM m_user WHERE user_id = ?", userId);

        return rowNumber;

    }

    @Override
    public void userCsvOut() throws DataAccessException {

    }
}

UserService.java
package com.example.demo.login.domain.service;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.example.demo.login.domain.model.User;
import com.example.demo.login.domain.repository.UserDao;

@Service
public class UserService {
    @Autowired
    @Qualifier("UserDaoJdbcImpl2")
    UserDao dao;

    public boolean insert(User user) {
        // insert実行
        int rowNumber = dao.insertOne(user);
        // 判定用変数
        boolean result = false;

        if (rowNumber > 0) {
            // insert成功
            result = true;
        }
        return result;
    }

    public int count() {
        return dao.count();
    }

    public List<User> selectMany() {
        // 全件取得
        return dao.selectMany();
    }

    public User selectOne(String userId) {
        // selectOne実行
        return dao.selectOne(userId);
    }

    public boolean updateOne(User user) {

        // 判定用変数
        boolean result = false;

        // 1件更新
        int rowNumber = dao.updateOne(user);

        if (rowNumber > 0) {
            // update成功
            result = true;
        }

        return result;
    }

    public boolean deleteOne(String userId) {

        // 1件削除
        int rowNumber = dao.deleteOne(userId);

        // 判定用変数
        boolean result = false;

        if (rowNumber > 0) {
            // delete成功
            result = true;
        }
        return result;
    }
}


5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2