概要
データアクセスフレームワークであるSpring JDBCを使用する方法についてまとめた。
当記事では、JdbcTemplateの更新処理であるupdateメソッドの使い方について紹介する。
前提
以下の記事の続きとなる。
概要 データアクセスフレームワークであるSpring JDBCを使用して、H2DBにアクセスする方法についてまとめた。 当記事ではSpring JDBCの特徴と、H2DBにアクセスするための準備方法について紹介する。 […]
概要 データアクセスフレームワークであるSpring JDBCを使用する方法についてまとめた。 当記事ではDAOの作成と、DBアクセスの動確を行う方法について紹介する。 ※尚、DAOパターンとは何かについての説明は割愛する &n[…]
特徴
データベースに対する更新操作(INSERT、UPDATE、DELETE)を実行する。
実行したクエリによって、影響を受けた行数を整数値で返却する。
使い方
JdbcTemplate.updateメソッドは以下のように使用する。
SQL文字列,
バインドするラメータ
)
使用例
実際にJdbcTemplate.updateメソッドの使用例について紹介する。
INSERT処理
生徒情報を新規作成する。
インターフェース
StudentDao.java
/** 生徒情報の作成 */
int createStudent(Student student);
実装
JdbcStudentDao.java
@Override
public int createStudent(Student student) {
var sql = "INSERT INTO student (grade, name, class_name, memo) VALUES (?, ?, ?, ?)";
return jdbcTemplate.update(sql, student.getGrade(), student.getName(), student.getClassName(),
student.getMemo());
}
使用結果
FooMain.java
// 生徒情報の作成
var student = new Student();
student.setGrade(5);
student.setName("田中太郎");
student.setClassName("5-D");
student.setMemo("良好な成績");
int res = studentDao.createStudent(student);
System.out.println("新規作成結果:" + res);
// ------------------------
// コンソール
// ------------------------
// 新規作成結果:1
UPDATE処理
生徒IDに紐づく生徒名を変更する。
インターフェース
StudentDao.java
/** 生徒名の更新 */
int updateStudentName(Student student);
実装
JdbcStudentDao.java
@Override
public int updateStudentName(Student student) {
var sql = "UPDATE student SET name = ? WHERE id = ?";
return jdbcTemplate.update(sql, student.getName(), student.getId());
}
使用結果
FooMain.java
// 生徒情報の更新
var student = new Student();
student.setName("テスト太郎");
student.setId(1);
int res = studentDao.updateStudentName(student);
System.out.println("更新結果:" + res);
// ------------------------
// コンソール
// ------------------------
// 更新結果:1
DELETE処理
生徒IDに紐づくテスト情報を削除する。
インターフェース
StudentDao.java
/** 生徒に紐づくテスト情報の削除 */
int deleteTest(int id);
実装
JdbcStudentDao.java
@Override
public int deleteTest(int id) {
var sql = "DELETE FROM test_point WHERE student_id = ?";
return jdbcTemplate.update(sql, id);
}
使用結果
FooMain.java
// 生徒に紐づくテスト情報の削除
int res = studentDao.deleteTest(3);
System.out.println("削除結果:" + res);
// ------------------------
// コンソール
// ------------------------
// 削除結果:2
補足
生徒情報を作成して自動生成された生徒IDをもとに、テスト情報を作成するときはKeyHolderオブジェクトを使用する。
生徒情報作成(生徒IDを返却)
生徒情報を作成した後、自動生成された生徒IDを取得するメソッドを用意する。
インターフェース
StudentDao.java
/** 生徒情報を作成して生徒ID取得 */
int insertStudentAndGetId(Student student);
実装
JdbcStudentDao.java
@Override
public int insertStudentAndGetId(Student student) {
var sql = "INSERT INTO student (grade, name, class_name, memo) VALUES (?, ?, ?, ?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(connection -> {
PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, student.getGrade());
ps.setString(2, student.getName());
ps.setString(3, student.getClassName());
ps.setString(4, student.getMemo());
return ps;
}, keyHolder);
// 生徒IDを取得
return keyHolder.getKey().intValue();
}
KeyHolderオブジェクトは、挿入操作で生成された主キー(今回は自動生成された生徒ID)を保持するために使用される。
ps.setInt(1, student.getGrade());
ps.setString(2, student.getName());
ps.setString(3, student.getClassName());
ps.setString(4, student.getMemo());
return ps;
JdbcTemplateのupdateが隠蔽している、JDBC APIをカスタマイズする。
本来はPreparedStatementを実行して処理結果件数を返却するが、今回は処理結果件数ではなくて自動生成IDを返却するよう修正する。
PreparedStatementにStatement.RETURN_GENERATED_KEYSを指定することで、SQL文(特にINSERT文)の実行後に自動生成された主キーを取得できる。
※JDBC APIの機能
JdbcTemplate.updateメソッドにKeyHolderオブジェクトを渡すことで、挿入によって自動生成された主キーを保持できる。
return keyHolder.getKey().intValue();
KeyHolderオブジェクトが保持する主キーを返却する。
テスト情報作成
テスト情報を新規作成するメソッドを用意する。
インターフェース
StudentDao.java
/** テスト情報の作成 */
int insertTest(TestPoint test);
実装
JdbcStudentDao.java
@Override
public int insertTest(TestPoint test) {
var sql = "INSERT INTO test_point (student_id, japanese, mathematics, evaluation, test_date) VALUES (?, ?, ?, ?, ?)";
return jdbcTemplate.update(sql, test.getStudentId(), test.getJapanese(), test.getMathematics(),
test.getEvaluation(), test.getTestDate());
}
生徒情報とテスト情報の作成
生徒情報を作成した後で自動生成される生徒IDをもとに、テスト情報を作成する。
尚、トランザクションは今回は考慮していない。
使用結果
FooMain.java
// 生徒情報と紐づく1件のテスト情報の作成
var student = new Student();
student.setGrade(6);
student.setName("鈴木次郎");
student.setClassName("6-D");
student.setMemo("良好な成績");
int studentId = studentDao.insertStudentAndGetId(student);
var test = new TestPoint();
test.setStudentId(studentId);
test.setJapanese(90);
test.setMathematics(80);
test.setEvaluation("優秀");
test.setTestDate(new Date());
studentDao.insertTest(test);
// 全生徒情報を取得
List<Student> studentList = studentDao.findAllStudens();
studentList.forEach(s -> System.out.println(s));
// ------------------------
// コンソール
// ------------------------
// Student(id=1, grade=1, name=山田太郎, className=1-A, memo=良好な成績, tests=[TestPoint(id=1, japanese=80, mathematics=70, evaluation=良好, testDate=2023-05-22, studentId=1), TestPoint(id=4, japanese=85, mathematics=90, evaluation=非常に良い, testDate=2023-09-30, studentId=1)])
// Student(id=2, grade=2, name=佐藤花子, className=2-B, memo=スポーツ万能, tests=[TestPoint(id=2, japanese=90, mathematics=65, evaluation=優秀, testDate=2023-05-22, studentId=2), TestPoint(id=5, japanese=60, mathematics=80, evaluation=普通, testDate=2023-09-30, studentId=2)])
// Student(id=3, grade=3, name=鈴木一郎, className=3-C, memo=芸術に秀でる, tests=[TestPoint(id=3, japanese=75, mathematics=85, evaluation=可, testDate=2023-05-22, studentId=3), TestPoint(id=6, japanese=85, mathematics=90, evaluation=非常に良い, testDate=2023-09-30, studentId=3)])
// Student(id=4, grade=6, name=鈴木次郎, className=6-D, memo=良好な成績, tests=[TestPoint(id=7, japanese=90, mathematics=80, evaluation=優秀, testDate=2024-02-24, studentId=4)])