Spring4(JDBC)
はじめに
Springは、Javaでアプリケーションを作成する上で欠かすことのできないフレームワークです。 Springでデータアクセス層にアクセスするために用いられるSpring JDBCについてご紹介します。
以下の内容をご紹介します。
(1)Springにおけるデータアクセス技術
(2)Spring JDBCの利用
サンプルコード
(1)Springにおけるデータアクセス技術
データベースにアクセスする技術として、JDBC、Hibernate、JPAなどがあります。Springは新たなデータアクセス技術ではなく、既存のデータアクセス技術をより使いやすくするための連携機能を提供しています。
Springと連携したJDBCがSpring JDBCというわけです。
1-1 Springを用いるメリット
Springと連携することで様々なメリットを得られます。
《Springとの連携で得られるメリット》
- データアクセス処理がシンプルになる
- Springのトランザクション機能を利用できる
- Springの提供する体系化されたデータアクセス例外を利用できる Springがデータアクセス技術独自の例外を汎用的なデータベース例外に変換してくれる。
【Springに用意されている汎用的なデータアクセス例外の例】
例外クラス | エラーの原因 |
DataAccessResourceFailureException | データソースとの接続に失敗 |
BadSqlGrammarException | SQLの文法エラー |
EmptyResultDataAccessException | 取得できるはずのデータが存在しない |
ConcurrencyFailureException | 同時実行の失敗 |
DeadlockLoserDataAccessException | デッドロックの発生 |
DuplicateKeyException | データの挿入・更新時に主キー or 一意制約に違反 |
DataIntegrityViolationException | データの挿入・更新時に整合性制約に違反 |
PermissionDeniedDataAccessException | 特定の要素(DBテーブルなど)へのアクセスが許可されていない |
1-2 データベース接続管理
データベースに接続する場合は、データベースに接続するための必要な情報(JDBCドライバー、データベースURL、ユーザ名、パスワード 等)を管理してくれるデータソースを準備する必要があります。また、変更を容易にするため、データベースに接続するための必要な情報は、プロパティファイルを準備して記述しましょう。今回は、Apacheソフトウェア財団がOSSとして提供しているDBCP(Apache Commons DBCP)をXML形式のBean定義ファイルで用いたデータソースの実装についてご紹介します。
<!-- XML形式のBean定義ファイル -->
<?xml version="1.0" encoding="UTF-8"?>
<!-- スキーマの使用はbeansタグ内でスキーマを定義する必要がある -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- location属性にプロパティファイルのパスを指定する -->
<context:property-placeholder location="application.properties"/>
<!-- DBCPのデータソース定義箇所 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- XML形式のBean定義ファイルにおけるBean定義 -->
<!-- JdbcTemplateクラスのBean定義 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
<!-- NamedParameterJdbcTemplateクラスのBean定義 -->
<bean class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
</beans>
#データベースに接続するための必要な情報を記述したプロパティファイル
jdbc.driverClassName = com.mysql.cj.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/db_ex?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
jdbc.username = root
jdbc.password = forStudy
【プロパティファイルの活用イメージ】
(2)Spring JDBCの利用
Spring JDBCには、2つの主なクラスがあります。
《Spring JDBCのクラス》
- JdbcTemplateクラス メソッドの種類が豊富であり、直接利用できるAPIの範囲も広い。
- NamedParameterJdbcTemplateクラス SQLのパラメータに任意の名前を付けてSQL文を発行するメソッドが提供されている。
2-1 SQLの発行方法(SELECT文)
SELECE文のSQLを発行する場合に用いる代表的なメソッドをご紹介します。
《SELCT文発行メソッド》
queryForObject()メソッドやquery()メソッドはオーバーロードによりいくつかの種類が存在するので、それらについては、SpringのJavadocを参照してください。
1レコードを処理する場合に使用するメソッド
queryForObject(String sql , ClassSE<T> requiredType , Object args…);
第1引数:SQLを文字列で指定
第2引数:戻り値の型を示すClassオブジェクトを指定
第3引数以降:SQL内のパラメータ(※)の値を指定
※:SQL文中で値を確定させるのではなく、実行時に値を代入することを示す位置指定子です。「?」を用います。
queryForObject(String sql , ClassSE<T> requiredType , Object args…);
第1引数:SQLを文字列で指定
第2引数:戻り値の型を示すClassオブジェクトを指定
第3引数以降:SQL内のパラメータ(※)の値を指定
※:SQL文中で値を確定させるのではなく、実行時に値を代入することを示す位置指定子です。「?」を用います。
複数のレコードを処理する場合に使用するメソッド
query(String sql , ResultSetExtractor<T> rse , Object args…);
第1引数:SQLを文字列で指定
第2引数:ドメインに変換して戻り値で返す処理を記述する
第3引数以降:SQL内のパラメータの値を指定
queryForObject()メソッドとquery()メソッドの違いは、レコードを1件ずつ処理するか複数まとめて処理するかです。ドメインに変換するqueryForObject()メソッドもあります。query(String sql , ResultSetExtractor<T> rse , Object args…);
第1引数:SQLを文字列で指定
第2引数:ドメインに変換して戻り値で返す処理を記述する
第3引数以降:SQL内のパラメータの値を指定
queryForObject()メソッドやquery()メソッドはオーバーロードによりいくつかの種類が存在するので、それらについては、SpringのJavadocを参照してください。
2-2 SQLの発行方法(INSERT/UPDATE/DELETE文)
INSERT/UPDATE/DELETE文の発行は、update()メソッドを使うだけです。
《INSERT/UPDATE/DELETE文発行メソッド》
update(String sql , Object args…);
第1引数:SQLを文字列で指定
第2引数以降:SQL内のパラメータの値を指定
第1引数:SQLを文字列で指定
第2引数以降:SQL内のパラメータの値を指定
サンプルコード
Spring JDBCを用いてデータベース操作を行うサンプルコードをご紹介します。 各クラスの階層関係及び使用するデータベースは、次のようになります。
【各クラスの階層関係】
【データベース接続環境】
ユーザ名 | root |
パスワード | forStudy |
ホスト名 | localhost |
ポート番号 | 3306 |
データベース名 | db_ex |
【テーブル:商品一覧】
列名 | データ型 | 制約 |
id | INT | NOT NULL , PRIMARY KEY |
name | VARCHAR(100) | - |
price | INT | - |
id INT |
name VARCHAR(100) |
price INT |
1 | ○○○小説 | 800 |
2 | ABC資格 参考書 | 2500 |
3 | ABC資格 問題集 | 2800 |
4 | △△△技術書 | 4200 |
5 | □□□漫画全巻 | 3200 |
//プレゼンテーション層パッケージ
package sample;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import sample.springjdbc.bujiness.domain.Book;
//コントローラの代わとしてmain()メソッドを実行する
public class SampleRun {
public static void main(String[] args) {
//SpringコンテナをBean定義ファイルにより生成
String classPath = "sample/config/spring-db.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(classPath);
//JdbcTemplateオブジェクトを取得
JdbcTemplate jdbcTemplate = ctx.getBean(JdbcTemplate.class);
//SELECT文
//queryForObjectメソッド
String sql = "SELECT COUNT(*) FROM 商品一覧";
int count = jdbcTemplate.queryForObject(sql, Integer.class);
System.out.println("レコード数:" + count + "件"+ "¥n");
//SELECT文
//queryメソッド
sql = "SELECT * FROM 商品一覧";
Book book = jdbcTemplate.query(sql
, new ResultSetExtractor<Book>() {
public Book extractData(ResultSet rs) throws SQLException ,DataAccessException {
if (!rs.next()) { return null; }
Book book = new Book();
while (rs.next()) {
System.out.println("id : " + rs.getInt("ID"));
System.out.println("name : " + rs.getString("NAME"));
System.out.println("price : " + rs.getInt("PRICE") + "¥n");
}
return book;
}}
);
// INSERT/UPDATE/DELETE 文
//INSERT文
book = new Book();
book.setId(6);
book.setBookName("123書籍");
book.setPrice(2700);
//INSERT文
sql = "INSERT INTO 商品一覧 (ID , NAME , PRICE)"
+ "VALUES(? , ? , ?)";
jdbcTemplate.update(sql , book.getId() , book.getBookName() , book.getPrice());
//UPDATE文
sql = "UPDATE 商品一覧 SET PRICE = 9999 WHERE ID = ?";
jdbcTemplate.update(sql , book.getId());
System.out.println("INSERT/UPDATE後");
sql = "SELECT * FROM 商品一覧";
book = jdbcTemplate.query(sql
, new ResultSetExtractor<Book>() {
public Book extractData(ResultSet rs) throws SQLException ,DataAccessException {
if (!rs.next()) { return null; }
Book book = new Book();
while (rs.next()) {
System.out.println("id : " + rs.getInt("ID"));
System.out.println("name : " + rs.getString("NAME"));
System.out.println("price : " + rs.getInt("PRICE") + "¥n");
}
return book;
}}
);
//DELETE文
sql = "DELETE FROM 商品一覧 WHERE ID = 6";
jdbcTemplate.update(sql);
}
}
//ビジネスロジック層(ドメイン)パッケージ
package sample.springjdbc.bujiness.domain;
public class Book {
private Integer id;
private String bookName;
private Integer price;
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getBookName() { return bookName; }
public void setBookName(String bookName) { this.bookName = bookName; }
public Integer getPrice() { return price; }
public void setPrice(Integer price) { this.price = price; }
}
レコード数:5件
id : 2
name : ABC資格 参考書
price : 2500
id : 3
name : ABC資格 問題集
price : 2800
id : 4
name : △△△技術書
price : 4200
id : 5
name : □□□漫画全巻
price : 3200
INSERT/UPDATE後
id : 2
name : ABC資格 参考書
price : 2500
id : 3
name : ABC資格 問題集
price : 2800
id : 4
name : △△△技術書
price : 4200
id : 5
name : □□□漫画全巻
price : 3200
id : 6
name : 123書籍
price : 9999
id : 2
name : ABC資格 参考書
price : 2500
id : 3
name : ABC資格 問題集
price : 2800
id : 4
name : △△△技術書
price : 4200
id : 5
name : □□□漫画全巻
price : 3200
INSERT/UPDATE後
id : 2
name : ABC資格 参考書
price : 2500
id : 3
name : ABC資格 問題集
price : 2800
id : 4
name : △△△技術書
price : 4200
id : 5
name : □□□漫画全巻
price : 3200
id : 6
name : 123書籍
price : 9999
まとめ
「Spring JDBC」についてご紹介しました。
お役に立てると幸いです。
↑