[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 メーリングリストの案内