[s2container-php5:85] Re: 【質問】s2dao.php5に関して2点(PRADO連携・update)
Yusuke Hata
[E-MAIL ADDRESS DELETED]
2007年 3月 13日 (火) 00:29:14 JST
ハタです。こんばんわ
まず、S2Dao_DBMetaDataFactoryのclass_exists($dbmd)は
class_exists($dbmd, false)が正解でした。
こちらは私の修正ミスで、本来ならば存在しないクラスのロードは行わないように
実装すべき点でした。(修正しておきます)
また、本来PDOはMySQLドライバ実装の動きをしますが(getColumnMetaなどについて)、
それの実装がされていないPDOドライバOracleやSybaseなどと互換を持つために用意しているのが
DBMetaDataインタフェースになっています。
なので、MySQLについてはS2Dao_StandardDbMetaDataクラスで実装しているとおりで問題がないハズです。
この件についてはclass_exists($dbmd, false)として、
MySQLではS2Dao_StandardDbMetaDataを使うようにしてください。
# 私の怠慢でドキュメントに残していない部分が多いですねorz
そして
> S2Dao_NotSingleRowUpdatedRuntimeException
> Description
> Target for update must be single row(actual:0).(ProductEntity)
これはMySQL以外でもおこりゆる更新が行われなかった場合の例外なのですが
この件については、どう対応するかは "実装次第" となると思います。
更新が行われなかった際にfalseを返すとか、更新されなかったので0(integer)を返すというのは
更新されている状態(値)が判別しにくいため、DAOの例外として上記どおりの実装になっています。
(本家Javaも同じ実装)
で、この例外をどのように扱うかの一実装としてS2DaoAssertAtLeastOneRowInterceptorがあげられます。
org.seasar.dao.interceptorsのパッケージにあるのですが
上記のinterceptorは更新結果が1件未満の場合に例外を発生させるもの(今回の例外実装と同じ)です。
もし、更新がなくとも処理は継続したい && try/catchを含めないとするならば、上記のようにinterceptor内で
綴じ込めてしまうのも1つの実装パターンと思います。
また、上記のようなinterceptorを含むdiconの記述例は以下になります。
<components>
<component class="EmployeeDao">
<aspect>
<component class="S2DaoInterceptor">
<aspect>
<component class="S2DaoAssertAtLeastOneRowInterceptor" />
</aspect>
</component>
</aspect>
</component>
</components>
ということで、投げやりですがDAOの実装として更新がなかった場合の実装は
アプリ任せてしまう他、ないものと考えています。
以上です。よろしくお願いします。
On Mon, 12 Mar 2007 23:08:08 +0900
"Yoshinari Ueyama" <[E-MAIL ADDRESS DELETED]> wrote:
> 植山です。
> 週末にPHPでのプログラミングを楽しんだのですが、その際に発生したことに
> 関して2点ほど質問があります。いろいろとご意見をお聞かせください。
>
> 1.Mysqlでのupdate処理
>
> 今までSQLITEのみで作業をしていたのは片手落ち、MysqlでのDB操作も試さね
> ば・・・と思い、 MYSQLを用いたS2Daoプログラミングを行っていくと、下記
> のようなエラーが発生しました。
>
> S2Dao_NotSingleRowUpdatedRuntimeException
> Description
> Target for update must be single row(actual:0).(ProductEntity)
>
> データの編集画面において、データを変更せずにdaoのupdate($entity)メソッ
> ドを実行した際に発生することがわかり、 おそらく下記の挙動が原因だと推
> 測しています。
>
> -------------------------------------------------------------------------------------------------------------------------------
> http://dev.mysql.com/doc/refman/4.1/ja/update.html
> カラムの値がそのカラムの現在の値に設定される場合、MySQL はそれが現在の
> 値であることを認識し、更新処理を行いません。
> -------------------------------------------------------------------------------------------------------------------------------
>
> これは、本来どのように対処すべきなのでしょうか?
> 1)画面入力値チェックの一環としてデータが変更されていないことを確認
> し、変更されていなければupdate処理を実行しない。
> 2)エラーが発生しないようにS2Daoの修正を行う。
>
> 2)S2Dao_MySQLDBMetaDataクラスについて
>
> S2Base.PHP5のPRADO pluginとS2Dao.PHP5を用いたプログラムを実行したとこ
> ろ、下記のようなエラーが発生しました。
>
> S2Dao_SQLRuntimeException
>
> Description
> SQLException occured, because [Warning]
> PradoBase::include_once(S2Dao_MySQLDBMetaData.php)
> [<a
> href='function.PradoBase-include-once'>function.PradoBase-include-once
> </a>]: failed to open stream: No such file or directory
> (@line 98 in file
> /private/var/www/public_html/prado/framework/PradoBase.php).
>
> これは、S2Dao_DBMetaDataFactoryの下記の処理実行時に
> class S2Dao_DBMetaDataFactory {
>
> const DBMetaData_Suffix = 'DBMetaData';
>
> public static function create(PDO $db, S2Dao_Dbms $dbms){
> $dbmd = get_class($dbms) . self::DBMetaData_Suffix;
> if(class_exists($dbmd)){
> return new $dbmd($db, $dbms);
> }
> return new S2Dao_StandardDBMetaData($db, $dbms);
> }
> }
>
> S2Dao_MySQLDBMetaDataクラスをロードする必要が出てきて、
>
> PradoBaseクラスの下記メソッドが実行された際に
> public static function autoload($className)
> {
> include_once($className.self::CLASS_FILE_EXT);
> if(!class_exists($className,false) &&
> !interface_exists($className,false))
> self::fatalError("Class file for '$className' cannot be
> found.");
> }
>
> S2Dao_MySQLDBMetaData.phpが存在していないために発生したと推測していま
> す。(あまり深くソースを追ってませんが・・)
>
> 今は、S2Dao_MySQLDBMetaDataを継承しただけのS2Dao_MySQLDBMetaDataクラス
> が定義された S2Dao_MySQLDBMetaData.class.phpを作成し、エラーが発生しな
> いようにしましたが、本来はどのように対処すべきでしょうか?
>
> 以上です。
>
--
Yusuke Hata <[E-MAIL ADDRESS DELETED]>
blog: http://blog.xole.net/
S2Container-PHP5 メーリングリストの案内