DBIInterceptorをアスペクトした場合は、Pointcutに適合したメソッドが実行されます。 DBIInterceptorは、メソッドの戻り値が文字列の場合は、SQLクエリとして扱います。 メソッドの戻り値が配列の場合は、1番目の値をSQLクエリ、2番目の値をSQL発行時のコンテキストとして 扱います。
SQLクエリが取得できた場合は、データベースに発行して結果を メソッドの戻り値として return します。 データベースへのSQLクエリの発行は、DBIのPrepared Statementが使用されます。 Prepared Statementにバインド されるvalueは、メソッド引数が使用されます。メソッドの戻り値が配列の場合は、2番目の値がバインドvalueとして扱われます。
PdoInterceptorには、O/Rマップ機能や自動SQL構築機能は実装されていません。
NOTE | |
---|---|
DBIInterceptorの例は example/example14 にあります。 |
PrefectureテーブルにアクセスするPrefectureDaoクラスを作成します。 PrefectureDaoクラスには、Prefectureテーブルから全件を取得するfind_allメソッドを実装します。 メソッドの戻り値としてデータベースに発行するSQLクエリを返します。
module Example class PrefectureDao s2comp s2aspect :interceptor => "dbi.interceptor" def find_all return 'select * from prefecture' end end end
次の処理を行うrun.rbを作成します。
require 'rubygems' require 'dbi' require 's2container' require 'seasar/dbi/interceptor' require 'example' s2comp(:class => DBI::DatabaseHandle, :namespace => "dbi", :autobinding => :none) { DBI.connect("dbi:SQLite3:example.db") } begin s2app[Example::PrefectureDao].find_all.each {|h| puts "#{h['id']}\t#{h['name']}" } rescue Seasar::DBI::DBIInterceptor::ConnectError => e s2logger.fatal(e.cause.class.name){"#{e.cause.message} #{e.cause.backtrace}"} rescue => e s2logger.fatal(e.class.name){"#{e.message} #{e.backtrace}"} ensure s2app[DBI::DatabaseHandle].disconnect if s2app[DBI::DatabaseHandle] end
PrefectureテーブルにアクセスするPrefectureDaoクラスを作成します。PrefectureDaoクラスには、 PrefectureテーブルからIDで検索するfind_by_idメソッドを実装します。 find_by_idメソッドの引数で検索するIDを指定します。SQLクエリへのIDの埋め込みは、「?」で行います。
module Example class PrefectureDao s2comp s2aspect :interceptor => "dbi.interceptor" def find_by_id(id) return 'select * from prefecture where id = ?' end end end
実行ファイルは次になります。
require 'rubygems' require 'dbi' require 's2container' require 'seasar/dbi/interceptor' require 'example' s2comp(:class => DBI::DatabaseHandle, :namespace => "dbi", :autobinding => :none) { DBI.connect("dbi:SQLite3:example.db") } begin s2app[Example::PrefectureDao].find_by_id(1).each {|h| puts "#{h['id']}\t#{h['name']}" } rescue Seasar::DBI::DBIInterceptor::ConnectError => e s2logger.fatal(e.cause.class.name){"#{e.cause.message} #{e.cause.backtrace}"} rescue => e s2logger.fatal(e.class.name){"#{e.message} #{e.backtrace}"} ensure s2app[DBI::DatabaseHandle].disconnect if s2app[DBI::DatabaseHandle] end
PrefectureテーブルにアクセスするPrefectureDaoクラスを作成します。PrefectureDaoクラスには、 Prefectureテーブルからタイトル名で検索するfind_by_nameメソッドを実装します。 メソッドの戻り値を配列とし、1番目の値にSQLクエリ、2番目の値にSQLクエリにバインドする値を配列で指定します。
module Example class PrefectureDao s2comp s2aspect :interceptor => "dbi.interceptor" def find_by_name(name) return "select * from prefecture where name = ?", name end end end
実行ファイルは次になります。
require 'rubygems' require 'dbi' require 's2container' require 'seasar/dbi/interceptor' require 'example' s2comp(:class => DBI::DatabaseHandle, :namespace => "dbi", :autobinding => :none) { DBI.connect("dbi:SQLite3:example.db") } begin s2app[Example::PrefectureDao].find_by_name("北海道").each {|h| puts "#{h['id']}\t#{h['name']}" } rescue Seasar::DBI::DBIInterceptor::ConnectError => e s2logger.fatal(e.cause.class.name){"#{e.cause.message} #{e.cause.backtrace}"} rescue => e s2logger.fatal(e.class.name){"#{e.message} #{e.backtrace}"} ensure s2app[DBI::DatabaseHandle].disconnect if s2app[DBI::DatabaseHandle] end
Daoクラスの中で直接DBIを使用する場合は、DaoクラスにDBIコンポーネントをインジェクションします。 次の例では、PrefectureDaoクラスにDBI::DatabaseHandleコンポーネントをプロパティインジェクションしています。 transactional_insertメソッドでは、インジェクションされたdbhコンポーネントを使用してトランザクションを開始しています。
module Example class PrefectureDao s2comp s2aspect :interceptor => "dbi.interceptor", :pointcut => /^insert/ def initialize @dbh = :di, DBI::DatabaseHandle end def transactional_insert(id, name) result = nil @dbh['AutoCommit'] = false begin result = self.insert(id, name) @dbh.commit rescue => e s2logger.warn(self.class.superclass.name) { "transaction failed. #{e.class.name} #{e.message}" } @dbh.rollback end @dbh['AutoCommit'] = true return result end def insert(id, name) return 'insert into prefecture values(?, ?)' end end end
実行ファイルは次になります。
require 'rubygems' require 'dbi' require 's2container' require 'seasar/dbi/interceptor' require 'example' s2comp(:class => DBI::DatabaseHandle, :namespace => "dbi", :autobinding => :none) { DBI.connect("dbi:SQLite3:example.db") } begin puts s2app[Example::PrefectureDao].transactional_insert(48, "その他") rescue Seasar::DBI::DBIInterceptor::ConnectError => e s2logger.fatal(e.cause.class.name){"#{e.cause.message} #{e.cause.backtrace}"} rescue => e s2logger.fatal(e.class.name){"#{e.message} #{e.backtrace}"} ensure s2app[DBI::DatabaseHandle].disconnect if s2app[DBI::DatabaseHandle] end
Seasar::DBI::Paginateクラスは、データベースからのデータ取得の際にページングを行うユーティリティクラスです。 PrefectureDaoクラスにfind_by_dtoメソッドを実装し、ページングを行います。
module Example class PrefectureDao s2comp s2aspect :interceptor => "dbi.interceptor" def find_by_dto(dto) return "select * from prefecture where name like ? limit ? offset ?", [dto.name_like, dto.limit, dto.offset] end def find_total_by_dto(dto) return "select count(*) as total from prefecture where name like ?", dto.name_like end end require 'seasar/dbi/paginate' class PrefectureDto < Seasar::DBI::Paginate attr_accessor :name_like end end
次の処理を行う実行ファイルを作成します。
require 'rubygems' require 'dbi' require 's2container' require 'seasar/dbi/interceptor' require 'example' s2comp(:class => DBI::DatabaseHandle, :namespace => "dbi", :autobinding => :none) { DBI.connect("dbi:SQLite3:example.db") } begin dto = Example::PrefectureDto.new dto.limit = 5 dto.name_like = '%県' dto.total = s2app[Example::PrefectureDao].find_total_by_dto(dto)[0]["total"] puts "page : #{dto.page}" s2app[Example::PrefectureDao].find_by_dto(dto).each {|h| puts "#{h['id']}\t#{h['name']}" } dto.next puts "page : #{dto.page}" s2app[Example::PrefectureDao].find_by_dto(dto).each {|h| puts "#{h['id']}\t#{h['name']}" } rescue Seasar::DBI::DBIInterceptor::ConnectError => e s2logger.fatal(e.cause.class.name){"#{e.cause.message} #{e.cause.backtrace}"} rescue => e s2logger.fatal(e.class.name){"#{e.message} #{e.backtrace}"} ensure s2app[DBI::DatabaseHandle].disconnect if s2app[DBI::DatabaseHandle] end
Seasar::DBI::Paginate#get_total_page メソッド.
全件数を件数/ページ(limit)で割った全ページ数を返します。
Seasar::DBI::Paginate#page メソッド.
現在のページ番号を返します。
Seasar::DBI::Paginate#page= メソッド.
ページ番号を設定します。
Seasar::DBI::Paginate#offset メソッド.
現在のoffset位置を返します。
Seasar::DBI::Paginate#limit= メソッド.
1ページあたりの件数を設定します。
Seasar::DBI::Paginate#total メソッド.
全件数を返します。
Seasar::DBI::Paginate#total= メソッド.
全件数を設定します。
Seasar::DBI::Paginate#window_size メソッド.
ページウィンドウに表示するページ数を設定します。
Seasar::DBI::Paginate#next メソッド.
1ページ進めます。
Seasar::DBI::Paginate#next? メソッド.
次のページがあるかどうかを返します。
Seasar::DBI::Paginate#prev メソッド.
1ページ戻ります。
Seasar::DBI::Paginate#prev? メソッド.
前のページがあるかどうかを返します。
Seasar::DBI::Paginate#page_range メソッド.
ページウィンドウ内に収まるページ番号のRangeを返します。
© Copyright The Seasar Foundation and the others 2008-2009, all rights reserved. |