Spring > JDBCDataAccess

概要

SpringでJDBCでアクセスするとき、ローレベルな部分は面倒を見てくれる

  • コネクションオープン
  • ステートメントのプリペア、実行
  • resultsetのイテレーションの用意
  • 例外のマッピング
  • トランザクションの管理
  • Connection,Statement,Resultsetのクローズ

JDBC データアクセスのための選択肢

  • JdbcTemplate
    • NamedParameterJdbcTemplate
      • JdbcTemplateをラップして、SQLパラメータに名前をつけられる
    • SimpleJdbcTemplate
      • JdbcTemplateとNamedParameterJdbcTemplateのうち、よくつかわれる操作を統合
  • SimpleJdbcInsert and SimplejdbcCall
    • DBのメタデータを活用できる
    • テーブル名や、カラム名を指定するだけでいい。
  • RDBMS Object
    • MappingSqlQuery, SqlUpdate ,StoredProcedure
    • データアクセスレイヤでの初期化時に、再利用可能でスレッドセーフなオブジェクトを作成する
    • 後から、いろいろなパラメータを渡してメソッド呼び出す

パッケージ階層

  • core
    • JdbcTemplate
    • simpleサブパッケージ:SimpleJdbcTemplate,SimpleJdbcInsert ,SimpleJdbcCall
    • namedparamサブパッケージ:NamedParameterJdbcTemplate
  • datasource
    • DataSourceにアクセスするためのユーティリティ
    • DataSourceの実装(テスティング、JavaEEコンテナの外側で動かす)
    • embedded :HSQL や H2 を使ったインメモリDB
  • object
    • RDBMSを表現する、スレッドセーフで再利用可能なオブジェクト
    • クエリ、更新、ストアド
  • support
    • SQLException をdao パッケージに変換

JDBCコアクラスを使って基本的なJDBCの処理と例外ハンドリング

JdbcTemplate

  • やってくれること
    • リソースの生成と解放
    • JDBCのワークフローでの基本的なタスクを実行
    • SQLクエリ、アップデート、ストアドプロシージャの実行
    • ResultSetに対するイテレーション、返却パラメータの抽出
    • JDBC例外をdaoパッケージの例外に変換
  • 開発者がやること
    • コールバックを実装
      • SQLと必要なパラメータを提供する
      • 結果の抽出を実装
      • PreparedStatementCreator
      • CallableStatementCreator
      • RowCallbackHandler
  • DAOで使われる。JdbcTemplateを直接インスタンスまたはビーンとして参照
  • ベストプラクティス
    • JdbcTemplate は一度DataSourceが設定された後はスレッドセーフなので、複数のDAOで共有できる
    • よくやるのは、DataSourceをビーン定義しておいて、DAOにインジェクションした時に、JdbcTemplateを作成し保持する
    • 複数DBにアクセスするときは、DBのDataSourceごとにJdbcTemplateを作成

NamedParameterJdbcTemplate

  • ?のプレースホルダではなく、パラメータに名前を付けて扱える。
  • SQL中の変数は :var
  • パラメータ値の設定
    • Map
    • SqlParameterSource
    • BeanPropertySqlParameterSource : ビーンをパラメータに指定できる
    • getJdbcOperations() で JdbcTemplateにしかないAPIを使える

SimpleJdbcTemplate

  • Java5からのジェネリクスや可変長引数をサポート(JdbcTemplateもサポートされてる)
  • JdbcTemplateに比べてシンプルなAPI
  • 可変長引数を活用できるAPI
    • getJdbcOperations() で JdbcTemplateにしかないAPIを使える

SQLExceptionTranslator

  • SQLExceptions と DataAccessExceptionの間の変換を行う
  • SQLErrorCodeSQLExceptionTranslator がデフォルトで使われる実装
    • ベンダーに特化したコードを扱うため、SQLステートによる変換よりも正確
    • エラーコードによる変換は、SQLErrorCodesクラスに基づいて行われる。
      • SQLErrorCodesFactory が 設定ファイルsql-error-codes.xmlと使用しているDB名に基づいてSQLErrorCodesを生成する
  • 適用順は SQLExceptionTranslator のカスタム実装 > SQLErrorCodeSQLExceptionTranslator(fallback) > SQLStateSQLExceptionTranslator(fallback)

Executing statements

JdbcTemplate#execute

Running queries

  • 単一行の取得
    • JdbcTemplate#queryForXXX
  • 複数行の取得 (List<Map<String, Object>> )
    • JdbcTemplate#queryForList

Updating the database

JdbcTemplate#update

Retrieving auto-generated keys

JdbcTemplate#update(PreparedStatementCreator, KeyHolder)


DBコネクションのコントロール

DataSource

  • DBコネクションを取得するためのクラス
  • FWやコンテナがコネクションプールやトランザクション管理をアプリケーションから切り離せるようになる
  • 開発者はDBへの接続の詳細を気にしなくてよくなる
  • Spring JDBC層を使うときは、DataSourceはJNDI経由かサードパーティのコネクションプール実装をビーン定義して参照する
    • Apache Commons DBCP
    • C3P0
    • Spring が提供する実装はテストのため
  • DriverManagerDataSource
    • JDBCコネクションを得るためのテスト向けのクラス

DataSourceUtils

  • JNDIからのコネクションの取得
  • コネクションのクローズ
  • DataSourceTransactionManagerなどのスレッド単位のコネクションをサポート

SmartDataSource

  • RDBのコネクションを提供するクラス向けのインターフェース
  • 利用するクラスが、指定された操作の後にコネクションをクローズするかを問い合わせることができる
    • コネクションの再利用時に便利

AbstractDataSource

すべてのDataSource実装に共通する部分を実装した抽象クラス

SingleConnectionDataSource

  • SmartDataSourceの実装で、単一のコネクションをラップしているためクローズされない。
  • テスト用のクラスで、物理的なコネクションを使い合わすので、無駄な物理コネクションの生成がない

DriverManagerDataSource

  • DataSource実装で、JDBCドライバをビーンのプロパティで設定する
  • 毎回新しいコネクションを生成する
  • テストやJavaEEコンテナの外側でのスタンドアローンな環境向け
  • プーリング機能はないので、DriverManagerDataSourceの上にさらにcommons-dbcpのようなコネクションプールを使うのがおすすめ

TransactionAwareDataSourceProxy

  • Spring管理のトランザクションをDataSourceに入れたもの
  • 既存コードがDataSourceインターフェースを利用していて、Spring管理のトランザクションを使いたいときにのみ有効

DataSourceTransactionManager

  • 単一のJDBCデータソース向けのPlatformTransactionManager実装
    • コネクションを実行スレッドに紐づけてくれる
  • JDBCコネクションを取得するときは DataSourceUtils.getConnection(DataSource) で行わないとだめ
  • カスタムの分離レベルとクエリのタイムアウトを指定できる
    DataSourceUtils.applyTransactionTimeout(..)
    
  • 複数データソースを扱うときは、JtaTransactionManager に設定を切りかえできる

NativeJdbcExtractor

  • ベンダーに特化したJDBCのメソッドにアクセスしたいとき
  • JdbcTemplate をNativeJdbcExtractorで設定する
    • SimpleNativeJdbcExtractor
    • C3P0NativeJdbcExtractor
    • CommonsDbcpNativeJdbcExtractor
    • JBossNativeJdbcExtractor
    • WebLogicNativeJdbcExtractor
    • WebSphereNativeJdbcExtractor
    • XAPoolNativeJdbcExtractor

JDBCバッチ処理

  • 同じプリペアドステートメントを複数回コールするときはバッチにするとパフォーマンスが向上する。

JdbcTemplateでの基本的なバッチ処理

  • バッチ処理を実現するためには、BatchPreparedStatementSetterインターフェースを実装する
    • setValues() と getBatchSize()
      jdbcTemplate.batchUpdate(xxx, batchPreparedStatementSetter)
      
  • バッチ処理を適切なタイミングで終了する必要がある場合は、InterruptibleBatchPreparedStatementSetter インターフェースを実装する
    • ストリームによる更新やファイルからの読み込みによるバッチの場合
    • isBatchExhausted()

リストでのバッチ処理

  • JdbcTemplate,NamedParameterJdbcTemplate では、バッチ更新処理をパラメータ配列をわたすことで実現できる
    • NamedParameterJdbcTemplateの場合は、SqlParameterSource[]
      • SqlParameterSourceUtils#createBatch で生成
    • JdbcTemplateの場合は、List<Object[]>
      • Object[]は、?プレースホルダに対応

バッチ処理を複数に分ける

  • 長大なバッチ処理を、小さな単位で分けることができる
    • jdbcTemplate.batchUpdateにバッチ処理件数を指定する
    • 戻り値はint[][] : 各バッチ処理で、各更新での更新件数

SimpleJdbcクラスを使ってJDBCオペレーションを単純化

  • SimpleJdbcInsert とSimpleJdbcCall を使うとメタデータ処理により、クライアントでの設定作業が単純になる
    • JDBCドライバにより、DBのメタデータが取得される。
    • メタデータプロセッシングは、オーバライドまたはOFFにすることもできる

SimpleJdbcInsertでインサート

  • setDataSourceなどのインジェクション時にインスタンス作成し、テーブル名などを設定する
    • withTableName でテーブル名設定
  • execute(Map) で実行
    • キーはカラム名

SimpleJdbcInsertで自動生成キーを取得

  • usingGeneratedKeyColumns で自動生成キー対象のカラム名を指定
  • executeAndReturnKey / executeReturningKeyHolder で自動生成されたキーを取得

SimpleJdbcInsertでインサート時に設定するカラムを指定

  • usingColumns

SqlParameterSourceでパラメータ値を指定する

  • BeanPropertySqlParameterSource
    SqlParameterSource parameters = new BeanPropertySqlParameterSource(actor)
    
  • MapSqlParameterSource
    • MapよりもaddValueがあって使いやすい
      SqlParameterSource parameters = new MapSqlParameterSource().addValue("first_name", actor.getFirstName())
      

SimpleJdbcCallでストアドプロシージャを呼ぶ

  • TODO

SimpleJdbcCallで明示的に宣言したパラメータを使う

  • TODO

SqlParameterの定義の仕方

  • TODO

SimpleJdbcCallでストアドファンクションを呼ぶ

  • TODO

SimpleJdbcCallでカーソルを扱う

  • TODO

JDBCオペレーションをオブジェクトとして使う

DBへのアクセスをオブジェクト指向的にあつかえる。

  • org.springframework.jdbc.object パッケージ

SqlQuery

  • DBへのクエリ
  • 再利用可能でスレッドセーフ
  • サブクラスでnewRowMapper(..)をオーバライドする
  • MappingSqlQuery, MappingSqlQueryWithParameters, UpdatableSqlQuery

MappingSqlQuery

  • 再利用可能なクエリ
  • DAOの初期化時に、ステートメントの作成(SQL、declareParameter())とcompile()をする
    • コンパイル後はスレッドセーフ
  • mapRow(..)をオーバライド
  • 1件の検索結果の取得:findObject
  • 複数件の検索結果の取得:execute

SqlUpdate

  • SqlQueryと大体同じ
  • update(..)を使う
  • サブクラス化してもメリットはない

StoredProcedure

TODO


パラメータとデータ値の共通的な問題

SQLの型情報を明示的に渡す

  • NULL値を正しく設定したいときなど
  • JdbcTemplateメソッドの付加パラメータ
  • SqlParameterValue
  • 名前つきパラメータの場合は、 BeanPropertySqlParameterSource、 MapSqlParameterSource

Handling BLOB and CLOB objects TODO

Passing in lists of values for IN clause TODO

Handling complex types for stored procedure calls TODO


組み込みDBのサポート

  • org.springframework.jdbc.datasource.embeddedパッケージでJavaの組み込みDBエンジンをサポート
    • HSQL, H2, Derby

なぜ組み込みDBか?

  • 開発フェーズに使うと便利
    • 設定の容易さ、起動の早さ、テスト容易性

DBインスタンスを作成する方法

  • ビーン定義で
    • <jdbc:embedded-database />
  • プログラマティックに
    • EmbeddedDatabaseBuilder

組み込みDBサポートを拡張する

データアクセスロジックを組み込みDBでテストする


データソースを初期化する TODO

タグ:

+ タグ編集
  • タグ:
最終更新:2012年08月08日 17:32
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。