[s2container-php5:34] S2Dao.PHP5+MySqlでのPDOトランザクションについて
Eishi Kuroda
kuroda @ jetsetrecords.net
2006年 6月 24日 (土) 20:52:26 JST
こんにちは。
先日からS2Dao.PHP5で色々試しているのですが、
下記環境でPDOトランザクションを利用しようとして問題が発生し困っています。
s2container.php5-1.1.0
s2dao.php5-1.1.0-rc3
MySQL 4.1.20
PHP 5.1.2
windows 2000
例えばMemberEntryServiceを下記のように設定します。
executeメソッドで、memberDaoを使って挿入処理を行います。
<component name="service" class="MemberEntryServiceImpl">
<aspect pointcut="execute">pdo.requiredTx</aspect>
<property name="memberDao">memberDao</property>
</component>
<component name="memberDao" class="MemberDao">
<aspect>dao.interceptor</aspect>
</component>
pdo.diconは下記の通りです。
<components namespace="pdo">
<component name="dataSource" class="S2Container_PDODataSource">
<property name="dsn">"mysql:host=localhost;dbname=test"</property>
<property name="user">"root"</property>
<property name="password">"test"</property>
<property name="option">
array(PDO::ATTR_ORACLE_NULLS => PDO::NULL_EMPTY_STRING,
PDO::ATTR_AUTOCOMMIT => false);
</property>
</component>
<component name="requiredTx" class="S2Dao_RequiredInterceptor" />
<component name="requiresNewTx" class="S2Dao_RequiresNewInterceptor" />
<component name="mandatoryTx" class="S2Dao_MandatoryInterceptor" />
<component name="notSupportedTx" class="S2Dao_NotSupportedInterceptor" />
</components>
この状態で、MemberEntryServiceImplからexecuteしてみると、
exception 'PDOException' with message 'There is already an active transaction' in
c:\www\test\lib\S2Dao\S2Dao\S2Dao_AbstractTxInterceptor.class.php:45
とエラーとなってしまいます。
(<aspect pointcut="execute">pdo.requiredTx</aspect>を外して、
PDO::ATTR_AUTOCOMMIT => trueとすれば挿入できます。)
S2Dao_AbstractTxInterceptor
および
S2Dao_RequiredInterceptor
を確認してみると、
S2Dao_AbstractTxInterceptorのhasTransactionメソッドで、
下記のように処理しているようです。
try {
$this->connection->beginTransaction();
} catch(Exception $e){
$this->begin = true;
return true;
}
S2Dao_RequiredInterceptorのinvoke側では、
下記のようになっています。
if (!$this->hasTransaction()) {
$this->begin();
$began = true;
}
hasTransaction()を呼び出すと、
beginTransaction()によってトランザクションが開始され、
S2Dao_RequiredInterceptor側で更にbegin()としているので、
ここでエラーになるようなのです。
そこで、とりあえずinvokeを下記の様にしてみたところ、
どうやら上手く動作しているようなのですが、
これで問題ないものなのでしょうか?
if (!$this->hasTransaction()) {
if (!$this->hasTransaction()) {
$this->begin(); //多分ここを通過することは無い
}
$began = true;
}
S2Dao_RequiredInterceptorを書き換えるものなんなので
何か他に良い解決方法があるのかも知れないと思うのですが、どうでしょうか?
では、よろしくお願いいたします。
黒田映史
S2Container-PHP5 メーリングリストの案内