ホーム画面からユーザー一覧画面に遷移し、ユーザーの詳細を表示するアプリケーションを作成して、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;
}
}