ログインしてさらにmixiを楽しもう

コメントを投稿して情報交換!
更新通知を受け取って、最新情報をゲット!

Seasarコミュのトランザクションについて

  • mixiチェック
  • このエントリーをはてなブックマークに追加
こんにちは。
S2Daoの"更新SQLの自動生成"をによってデータが更新されるの
を試しているのですが、これにDBのトランザクションを実装
しているのですが、トランザクションが効いていません。
※変更が適用されてしまっています。


構成は、FuncDaoImplクラスのwriteメソッドを実行すると、
Meisyo_mstDao(S2Dao自動生成)のupdateメソッドを実行する
というような構成です。

FuncDaoImpl.write(EntityBean) -> Meisyo_mstDao.update(EntityBean)
※トランザクションの設定は、FuncDaoImplクラスに対して
行っています。


S2Containerのトランザクションは「例外が発生した場合に
ロールバック、そうでなければコミット」とあったので、
updateメソッド実行後、連続してinsertメソッドを実行して
重複エラー(SQLRuntimeException)を発生させるようにしま
した。

その時のデバッグログは以下の通りです。
■デバッグログ
DEBUG 2006-10-13 15:48:36,062 [http-8080-Processor24] トランザクションを開始しました
DEBUG 2006-10-13 15:48:36,843 [http-8080-Processor24] 物理的なコネクションを取得しました
DEBUG 2006-10-13 15:48:36,843 [http-8080-Processor24] 論理的なコネクションを取得しました
DEBUG 2006-10-13 15:48:37,281 [http-8080-Processor24] 論理的なコネクションを閉じました
DEBUG 2006-10-13 15:48:37,328 [http-8080-Processor24] 論理的なコネクションを取得しました
DEBUG 2006-10-13 15:48:37,328 [http-8080-Processor24] UPDATE MEISYO SET naiyo = 'あああああわわわわわをををををんんんんん' WHERE kbn = '999' AND no = '9999999999'
DEBUG 2006-10-13 15:48:37,343 [http-8080-Processor24] 論理的なコネクションを閉じました
DEBUG 2006-10-13 15:48:37,359 [http-8080-Processor24] 論理的なコネクションを取得しました
DEBUG 2006-10-13 15:48:37,359 [http-8080-Processor24] INSERT INTO MEISYO (kbn, no, naiyo) VALUES ('999', '9999999999', 'あああああわわわわわをををををんんんんん')
DEBUG 2006-10-13 15:48:37,375 [http-8080-Processor24] 論理的なコネクションを閉じました
DEBUG 2006-10-13 15:48:37,375 [http-8080-Processor24] トランザクションをロールバックしました
org.seasar.framework.exception.SQLRuntimeException: [ESSR0071]SQLで例外(ErrorCode=1, SQLState=23000)が発生しました。理由はorg.seasar.framework.exception.SSQLException: [ESSR0072]SQLで例外(SQL=[INSERT INTO MEISYO (kbn, no, naiyo) VALUES (?, ?, ?)], ErrorCode=1, SQLState=23000)が発生しました


一番最後で「トランザクションをロールバックしました」と
なっているのですが、データがコミットされていました。


RuntimeExceptionだとうまくいかないのかと思い、SQLException
を自力でスロー下のですが、結果同じでした。
以下、その時のデバッグログです。
■デバッグログ(update後、"throw new SQLException"を実行した場合)
DEBUG 2006-10-13 16:21:33,281 [http-8080-Processor24] トランザクションを開始しました
DEBUG 2006-10-13 16:21:34,031 [http-8080-Processor24] 物理的なコネクションを取得しました
DEBUG 2006-10-13 16:21:34,031 [http-8080-Processor24] 論理的なコネクションを取得しました
DEBUG 2006-10-13 16:21:34,437 [http-8080-Processor24] 論理的なコネクションを閉じました
DEBUG 2006-10-13 16:21:34,484 [http-8080-Processor24] 論理的なコネクションを取得しました
DEBUG 2006-10-13 16:21:34,484 [http-8080-Processor24] UPDATE MEISYO SET naiyo = '3あああああわわわわわをををををんんんんん' WHERE kbn = '999' AND no = '9999999999'
DEBUG 2006-10-13 16:21:34,515 [http-8080-Processor24] 論理的なコネクションを閉じました
DEBUG 2006-10-13 16:21:34,515 [http-8080-Processor24] トランザクションをロールバックしました
java.sql.SQLException


Seasar2入門、公式HPを見ながらコーディングしているので
すがS2Daoとトランザクションの組み合わせのサンプルという
のが見当たらず、ハマってしまいました。

考えられることとして、"オートコミット"の状態にでもなって
いるのかと思い、調べているの(j2ee.dicon,server.xml)です
が、特に怪しいところはないように思えます。

何か構成の仕方がおかしいのでしょうか?何かご存知の方が
いらっしゃいましたら、アドバイスをお願い致します。


■開発環境
OS : Windows XP SP2
Tomcat : 5.5.17
Eclipse : 3.1.2
Seasar :
S2Dao : 1.0.35
DB : Oracle 10g(Release1)
※jarファイルは、S2Container/S2Daoのlibディレクトリの中身を全てWEB-INFに格納
 しました。(その他、Oracle10gのJDBCが含まれています)

【以下、ソース及びdiconファイル】
■Meisyo_mstdao.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.3//EN"
"http://www.seasar.org/dtd/components23.dtd">

<components>
<include path="jp/co/hogehoge/s2dao/sample/dao.dicon"/>
<component name="Meisyo_mst_FuncDao" class="jp.co.hogehoge.s2dao.sample.Meisyo_mst_FuncDaoImpl">
<aspect>j2ee.requiredTx</aspect> <!-- トランザクションを使いますよ〜というaspect -->
</component>
<component name="Meisyo_mstDao" class="jp.co.hogehoge.s2dao.sample.Meisyo_mstDao" >
<aspect>dao.interceptor</aspect> <!-- S2DAOを使いますよ〜というaspect(上のトランザクションを先に記述しないとトランザクション機能しない) -->
</component>
</components>


■FuncDaoImpl
package jp.co.hogehoge.s2dao.sample;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.List;

import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;

public class Meisyo_mst_FuncDaoImpl implements Serializable, Meisyo_mst_FuncDao {
private static final String PATH = "jp/co/hogehoge/s2dao/sample/Meisyo_mstdao.dicon";

public int write(Meisyo_mstEntity EntityBean) throws SQLException {
// コンテナの生成
S2Container container = S2ContainerFactory.create(PATH);
container.init();

// インスタンスをコンテナより取得
Meisyo_mstDao wmdao = (Meisyo_mstDao)container.getComponent(Meisyo_mstDao.class);

// 更新処理実行
wmdao.update(EntityBean);

// 更新処理実行 <----(ココで重複エラー)
wmdao.insert(EntityBean);

return 0;
}
}


■Meisyo_mstDao
package jp.co.hogehoge.s2dao.sample;

import java.sql.SQLException;
import java.util.List;

public interface Meisyo_mstDao {

/**
* アノテーション(Beanの指定)
*/
public static final Class BEAN = Meisyo_mstEntity.class;

/**
* 追加処理
* @param EntityBean Tableに対応するEntityBeanインスタンス
* @return 処理件数
*/
public int insert(Meisyo_mstEntity EntityBean) throws SQLException;

/**
* 更新処理
* @param EntityBean Tableに対応するEntityBeanインスタンス
* @return 処理件数
*/
public int update(Meisyo_mstEntity EntityBean) throws SQLException;
}

コメント(29)

Meisyo_mst_FuncDaoImplにトランザクションを設定しないと、意図した動きにならないんじゃないでしょうか。
>t-doiさん
>Meisyo_mst_FuncDaoImplにトランザクションを設定しない
>と、意図した動きにならないんじゃないでしょうか。

トランザクションの設定って、以下の部分ですよね?
これでMeisyo_mst_FuncDaoImplにかけているつもりなんです
が、何か違ってますか?
※Meisyo_mst_FuncDaoはMeisyo_mst_FuncDaoImplのインター
フェースです。

■Meisyo_mstdao.dicon
<component name="Meisyo_mst_FuncDao" class="jp.co.hogehoge.s2dao.sample.Meisyo_mst_FuncDaoImpl">
<aspect>j2ee.requiredTx</aspect> <!-- トランザクションを使いますよ〜というaspect -->
</component>
Meisyo_mst_FuncDaoImplのdiconでトランザクションの設定が
必要ですよ。
のぶさんの設定では、DAOがDBに接続しているときのものだけです。
そのDAOを利用している側のMeisyo_mst_FuncDaoImplでも設定が
必要です。
あってますね。私の誤読でした。
Meisyo_mst_FuncDaoImplのインスタンス取得はどのように行っているのでしょうか?
こいつもSeasarより取得しないとトランザクションのAOPが有効にならいと思います。
>つんちゃんさん
>Meisyo_mst_FuncDaoImplのdiconでトランザクションの設定が
>必要ですよ。

以下のようにしてみましたが、実行時にエラーになりますね。
■diconファイル
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.3//EN"
"http://www.seasar.org/dtd/components23.dtd">

<components>
<include path="jp/co/aafs/s2dao/sample/dao.dicon"/>
<component name="Win_meisyo_FuncDao" class="jp.co.aafs.s2dao.sample.Win_meisyo_FuncDaoImpl">
<aspect>j2ee.requiredTx</aspect> <!-- トランザクションを使いますよ〜というaspect -->
</component>

<component name="Win_meisyo_FuncDaoImpl" class="jp.co.aafs.s2dao.sample.Win_meisyo_FuncDaoImpl">
<aspect>j2ee.requiredTx</aspect> <!-- トランザクションを使いますよ〜というaspect -->
</component>

<component name="Win_meisyoDao" class="jp.co.aafs.s2dao.sample.Win_meisyoDao" >
<aspect>dao.interceptor</aspect> <!-- S2DAOを使いますよ〜というaspect(上のトランザクションを先に記述しないとトランザクション機能しない) -->
</component>
</components>

■エラー内容
[ESSR0045]interface jp.co.aafs.s2dao.sample.Win_meisyo_FuncDaoに複数のコンポーネント(jp.co.aafs.s2dao.sample.Win_meisyo_FuncDaoImpl, jp.co.aafs.s2dao.sample.Win_meisyo_FuncDaoImpl)が登録されています

具体的に、どのような設定でしょうか?以下の部分だと思って
いるのですが・・・。
<component name="Win_meisyo_FuncDaoImpl" class="jp.co.aafs.s2dao.sample.Win_meisyo_FuncDaoImpl">
<aspect>j2ee.requiredTx</aspect> </component>


>t-doiさん
Meisyo_mst_FuncDaoImplのインスタンスの取得はS2Container
から行っています。Meisyo_mst_FuncDaoインターフェース経由
ですので、呼び出し側(Servletなのですが)で、

S2Container container = S2ContainerFactory.create(PATH);
container.init();

Meisyo_mst_FuncDao wfdao = (Meisyo_mst_FuncDao)container.getComponent(Meisyo_mst_FuncDao.class);
初めまして。類人猿と申します。

実行時エラーについてですが上記のソースでは最後の行で
getComponentにMeisyo_mst_FuncDao.classを
渡してますよね?恐らくインターフェースの型を
渡してコンポーネントを取得しようとしていると
思うのですが、これではS2Containerが
「Win_meisyo_FuncDao」と「Win_meisyo_FuncDaoImpl」の
どちらをとってこればいいか判断できないはずです。
(どちらも同じインターフェースを使っているため)

文字列で登録した名称を指定してやればこの
エラーは解決すると思われます。

本題については自分も勉強中の身分なので
保留させて下さい(^^;
はじめまして。

Meisyo_mst_FuncDaoImplのwriteの中でS2Containerを新たに作っているようですが、ここが問題ではないでしょうか。

Meisyo_mst_FuncDaoImplにsetWin_meisyo_FuncDaoというようなsetterを用意して、Seasarにセットしてもらってください。

と、この説明で分かるでしょうか?
読み返して、やっぱり自分の説明が悪いようなので、もうちょっと詳しく書きます。

まず、Daoは、そのままで良いと思います。

問題のMeisyo_mst_FuncDaoImplですが、まずwriteメソッドの中の更新処理の手前までを、ばっさり削除します。

そして、Meisyo_mstDao wmdaoをプライベートなフィールドとして定義します。

最後に、wmdaoに値をセットするsetMeisyo_mstDaoというような名前のsetterメソッドを作ります。

これで、Meisyo_mst_FuncDaoImplだけみると、インスタンスを設定していないwmdaoという変数を使うように見えますが、ここでSeasarが大活躍します。

setterメソッドを呼び出して、コンポーネントとして登録されたDaoをセットしてくれるのです。

この動きがDIコンテナの肝ですね。インスタンスを取りに行くのではなく、外から入れて貰う(セットして貰う)のです。
ごめんなさい。
誤読して勘違いしていました。

Meisyo_mstdao:インターフェース
Meisyo_mstdaoImpl:実装クラス

インターフェース側のdiconで設定しているんですね。。。
Meisyo_mstdaoをDaoクラスと勘違いしていました。

なので、おそらく、
■Meisyo_mstdao.dicon
<component name="Meisyo_mst_FuncDao" class="jp.co.hogehoge.s2dao.sample.Meisyo_mst_FuncDaoImpl">
<aspect pointcut="write">
j2ee.requiredTx
</aspect> <!-- トランザクションを使いますよ〜というaspect -->
</component>

と、writeメソッドが呼ばれたらrequiredInterceptorを呼ぶように
明示的に設定すればいいかと思います。

お騒がせしました。
おお。みなさんありがとうございます。
残念ながら、DB(Oracle)がないので、今試せませんToT
月曜日にやってみたいと思います。

>JUNDUさん
Meisyo_mst_FuncDaoImplの中に問題がありそうですか。
ちょっと組み方を見直してみます。

>つんちゃんさん
>requiredInterceptorを呼ぶように明示的に設定すればいい
>かと思います。
<aspect pointcut="write"> がポイントですね。
実は、AOPの部分についてはいまだ勉強中のところがあります
ので、あまりよく理解できていません。ご指摘頂いた内容で
試してみたいと思います。
一つ忠告。
クラス名はわかりやすくした方がいいですよ〜。
サーバーサイドの構成としては、

ロジック−DAO−DB

という流れになります。
んで、diconの設定としては、

・j2ee.dicon:DBとの接続関係、およびトランザクション管理
・dao.dicon:DAOの設定
・ロジック.dicon:インターフェイスと実装クラスの設定

とあるわけです。
のぶさんの例だと、
・Meisyo_mstDao:DAOクラス
・Meisyo_mst_FuncDao:ロジックのインターフェイス
・Meisyo_mst_FuncDaoImpl:ロジックの実装クラス
となるわけです。
ところが、全部のクラス名にDAOって入っているから、どれが
どの役割を担っているのかわかりにくかった(爆

できれば、ロジックのインターフェイスは〜Logicにして、
実装クラスは〜LogicImplにするとわかりやすいです。
(たとえば今回のだと、insertLogicとinsertLogicImplにするとか)

なので、のぶさんの例だと、命名規約がわかりにくかったために
役割がいまいち見えにくく感じました。

整理すると、のぶさんの質問の主旨は、ロジック.diconに
requieredInterceptorを設定しているのに、ロジックが
呼ばれたときに使われていないっていうことかと思われます。
なので、トランザクション管理したいメソッドが呼ばれたときに
requieredInterceptorを明示的にアスペクトするようにすれば
対応できるのではないかと思います。
(もしもこちらの理解に間違いや問題があったら、突っ込んでください。)
>つんちゃんさん
Seasarのアスペクトですが、インターフェースを実装したクラスに設定する場合、ポイントカットを明示的に指定しない場合にはインターフェースに定義されたメソッドに設定されます。

なので、この場合、Meisyo_mst_FuncDaoにwriteメソッドがあれば不要なはずです。もちろん明示的に指定しても平気ですが、そうすると今後メソッドが増えた時にdiconファイルの書き換えが発生するので、ちょっと面倒になってしまいます。
>つんちゃんさん、JUNDUさん
JUNDUさんの

「Meisyo_mst_FuncDaoImplのwriteの中でS2Containerを新たに
作っているようですが、ここが問題ではないでしょうか。 」

というところを、FuncDaoImplの中で"Meisyo_mstDao wmdao"を
FuncDaoImplの呼び元であるプログラムより、writeの引数渡す
ように変更(アドバイスではsetterでしたが、試験的に変更の
簡単な引数での引き渡しにしました)したところ、トランザク
ションが正常に動作しました!!

ですが、原因・・・といいますか、この両者の違いがわかって
いません。^^;

ロジック的に"パラメータとして渡すのがDI的"という組み方で
あるというのは、Seasar入門にもありますので、考え方として
は理解できます。
ですが、S2Daoでこれが(アスペクトの部分ですかね?)なぜ
このような違いとなって現れたのかが理解できません。

よろしければ、この辺の動作について教えて下さい。
※「Seasar入門のこの辺に書いてあること!」とか、「公式
HPのここ読め!」とかでも結構です。


【以下、解決に至ったソースです】=========================================

■Meisyo_mstClient(FuncDaoImplの呼び元)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
S2Container container = S2ContainerFactory.create(PATH);
container.init();

Meisyo_mst_FuncDao wfdao = (Meisyo_mst_FuncDao)container.getComponent(Meisyo_mst_FuncDao.class);
Meisyo_mstDao wmdao = (Meisyo_mstDao)container.getComponent(Meisyo_mstDao.class);

// 更新情報をEntityBeanインスタンスに設定
Meisyo_mstEntity EntityBean = new Meisyo_mstEntity();
EntityBean.setKBN("999");
EntityBean.setNO("9999999999");
EntityBean.setNAIYO("11あああああわわわわわをををををんんんんん");

try
{
wfdao.write(wmdao,EntityBean);

} catch (SQLException sqlexp) {
System.out.println(sqlexp.toString());
} catch (Exception exp) {
System.out.println(exp.toString());
}
}


■FuncDaoImpl
public int write(Meisyo_mstDao dao,Meisyo_mstEntity EntityBean) throws SQLException {
// 更新処理実行
dao.update(EntityBean);

// わざと例外を発生
throw new SQLException();
}


それと、今回の更新プログラムで私の考えていた構成の構成図
(クラス図)です。Seasar2を勉強勉強しながら、スタンダード
的な構成をこのように考えていました。
※勉強のまとめ資料みたいなもんですので、不適切な記述も
あるかと思いますが、ご容赦願います^^;

図中の、
"Servlet" ・・・ Meisyo_mstClient
"機能Dao Impl" ・・・ Meisyo_mst_FuncDaoImpl
"データDao Impl" ・・・ Meisyo_mstDao
といった構成になります。

※Client側でFuncDaoImplのインスタンスを取得しても、構成
の方は変わらないような気がしてます。
> ですが、原因・・・といいますか、この両者の違いがわかっていません。^^;

説明が難しいのですが、S2ContainerFactory.create(PATH)という呼び出しは、新しいS2Containerのインスタンスを作ることを意味します。

つまり、修正前のコードでは、Meisyo_mst_FuncDaoImplを取り出すのに使ったS2ContainerとMeisyo_mstDaoを取り出すのに使ったS2Containerのインスタンスは別の物だということです。

そして、トランザクションを管理するTransactionManagerは、S2Containerが管理する物ですので、S2Containerのインスタンスが別々ということは、TransactionManagerも2つ別々のものが出来てしまっているということです。

その結果、Meisyo_mst_FuncDaoImplに設定したj2ee.requiredTxでトランザクションを開始したのに、そのトランザクションとは関係のないところでMeisyo_mstDaoが実行されているわけです。そちら側のS2Containerではトランザクションが開始されていないため、ロールバックが使えないというわけです。

少し簡単に書いてみましたが、このような説明で分かりますでしょうか?
>JUNDUさん

納得です。実は機能、コーディングをsetterを利用するように
改造しているうちに"インスタンスが異なる為に管理できなさ
そう"ということに、うすうす気がつきました(汗)
※実際に気づいたのは、diconファイルを眺めていたときです。

最終的な構成と所感を自分の日記にメモしておきました^^;

■のぶ日記
http://mixi.jp/view_diary.pl?id=245089800&owner_id=3773781
http://mixi.jp/view_diary.pl?id=245100309&owner_id=3773781

ということは、トランザクションを張りたいロジッククラス
(今回の場合は、FuncDaoImpl)で、それ以降に必要なDao、
Beanのインスタンスを予め作って(というか、ひとつの
Containerオブジェクトにまとめる)おく必要があるというこ
とですね。

今回のFuncDaoImplの場合、writeメソッドのみトランザクショ
ンを適用するので、pointcutに"write"を指定しました。
※あ、pointcutを複数指定したい場合はどうするんだろ・・・。
>のぶさん

Seasar2を使う場合、普段はS2Containerをシングルトンで使うことになると思います。そのために、SingletonS2ContainerFactoryというクラスがあります。

setterに書き換えてDIを使うようにすると、これも同じS2Container上にコンポーネントが対象ですので、やっぱりS2Containerは1つだけ使うのが普通です。

※話を簡単にするために、includeの話を端折っています。

さらに、S2StrutsやS2JSFなどのプロダクトと連携すると、自分で作るPOJOの部分にはS2Containerとか普通は出てきません。この場合はS2StrutsやS2JSFが内部でSingletonS2ContainerFactoryを使ってS2Container経由で作ったPOJOを呼んでくれます。

# Pointcutを複数指定する方法は、公式ドキュメントにあるはずですので探してみてください。
>JUNDUさん

ありがとうございます。なんとか理解が追いつきました(笑)

># Pointcutを複数指定する方法は、公式ドキュメントにあるはずですので探してみてください。

見つかりました。カンマ区切りにすればいいみたいです。
思ってた以上に簡単でした。
> のぶさん
話を整理できるかわかりませんが、整理してみます。
S2Containerを利用するということは、Servelet側がそれを読み込んで認識されているからです。
では、Servletが読み込んでいるものは何かというと、それはapp.diconになります。
普通、app.diconには、

app.dicon
├─ロジック1.dicon
│ ├─j2ee.dicon
│ └─alldao.dicon
│ ├─Dao1
│ ├─Dao2
│ │ ・
│ │ ・
├─ロジック2.dicon

という記述をします。
ここでロジック1.diconにrequieredInterceptorを設定しておくことで
Servlet側が、app.diconを読み込んだときに「ロジック1が呼ばれたらrequieredInterceptorを使ってトランザクション管理をするんだな」と認識されるわけです。

ところが、のぶさんはS2ContainerFactory.create(PATH)という呼び出しをして、新しいS2Containerのインスタンスを作ることでDaoを呼び出しています。
そのため、app.diconに書かれている最初の設定が無視されてしまっているのかと思われます。

こんな説明で理解してもらえますかね?
詳しい動きについては、JUNDOUさんの説明が詳しいかと思いますが、
全体の流れというかイメージがつかめてないように思えました。

蛇足でしたら、すみません。
>つんちゃんさん
>ここでロジック1.diconにrequieredInterceptorを設定してお
>くことでServlet側が、app.diconを読み込んだときに「ロジッ
>ク1が呼ばれたらrequieredInterceptorを使ってトランザクショ
>ン管理をするんだな」と認識されるわけです。

ここまで理解できます。かつ、この管理は同一のContainer
インスタンスの中で管理されているということですよね。


>ところが、のぶさんはS2ContainerFactory.create(PATH)という
>呼び出しをして、新しいS2Containerのインスタンスを作ること
>でDaoを呼び出しています。
>そのため、app.diconに書かれている最初の設定が無視されて
>しまっているのかと思われます。

"app.dicon"ってどれのことですかね?この名前のファイルは
S2Containerにもないのですが。今回で言うと"Meisyo_mstdao.dicon"
のことでしょうか?

今回のまずかったところは、

1.S2Containerインスタンス1にFuncDaoImplを入れている。
2.S2Containerインスタンス2にMeisyo_mstDaoを入れている。
3.トランザクションのAspectは、FuncDaoImplに指定している。

この為、
「S2Containerインスタンス1.FuncDaoImpl上でトランザクショ
ンは行われているが、動インスタンス上にMeisyo_mstDaoのイ
ンスタンスが存在しない為、S2Daoでのトランザクションまで
有効にならなかった。」

と思っています。
S2Containerのモデル上、トランザクションや一連のAspectを
適用するには、同一のContainerインスタンスに登録してあげ
ないといけないということですね。
これであってますかね?^^;

P.S.
下位のDaoやLogicに対してContainerインスタンスを渡して
いくという組み方もできますね。モデル的にDIの考え方から
脱線しますが(全実装がコンテナに依存してしまう・・・^^;)
>下位のDaoやLogicに対してContainerインスタンスを渡して
>いくという組み方もできますね。モデル的にDIの考え方から
>脱線しますが(全実装がコンテナに依存してしまう・・・^^;)

SingletonS2ContainerFactoryを使えば良いと思います。
>t-doiさん
>SingletonS2ContainerFactoryを使えば良いと思います。

SingletonS2ContainerFactoryの場合は、常に同じインスタンス
を使いまわすことになるんでしょうか?
入門書には、S2ContainerFactoryクラスを使用していますが、
実務ではどちらが適切なんですかね?私の理解の範囲では、

>下位のDaoやLogicに対してContainerインスタンスを渡して
>いくという組み方もできますね。モデル的にDIの考え方から
>脱線しますが(全実装がコンテナに依存してしまう・・・^^;)

のようなモデルでなければ、どちらも差がないように見えます。
HPの説明を見てるとapp.diconで作っておけば、PATHの指定が
なくてもいけるっぽいので、その分SingletonS2ContainerFactory
の方が楽なのかなと思います。
SingletonS2ContainerFactory#getContainer()
にて、いつでもS2のコンテナを取得できます。
したがって、下位にコンテナのインスタンスを引き渡す必要がなくなります。
SingletonS2ContainerFactoryについて補足です。

> SingletonS2ContainerFactoryの場合は、常に同じインスタンス
> を使いまわすことになるんでしょうか?

はい、そういうイメージでいいと思います。

そして、この場合は、直接diconファイルを指定せず、クラスパス直下のapp.diconという名前のdiconファイルを使う(より一般的には、app.diconで作ったdiconファイルをincludeする)形になります。
> のぶさん

Seasar2 (S2Container)からDIContainerのところに
SingletonS2ContainerFactoryやapp.diconの役割に
ついて書いてあります。

http://s2container.seasar.org/ja/DIContainer.html

こちらを参照してみてください。
app.diconは各種diconファイルを取りまとめる役割をしています。
app.diconに書かれている設定をServletContainerが解釈をして
DIしてくれているわけです。
>t-doiさん、JUNDUさん、つんちゃん

initメソッドで、コンテナのインスタンスが生成されて(もし
くは読込時に既に生成かな?)、getCompornentで取得という
ことになるのですね。app.diconって、モロ説明にありましたね。

すみません。気がつきませんでした ToT

私なりのまとめですが、コンテナの生成についてはSingletonS2ContainerFactory
で行うようにしようと思います。diconの管理が明確になりますし。
ですが、各インスタンスをBeanに受け渡すのはsetterで行いま
す。(通常は・・・です)
どこからでもインスタンスの取得が行えるのはよいのですが、
"インスタンスがない"や"取得したインスタンス内の値が変"
というような場合、インスタンスの発生元が不明確になる
(追いかけきれない)のが怖いです。それと、ほとんどの
BeanがS2Containerに依存するコーディングになり、独立性が
乏しくなるのかなという気がします。

※みんながS2Containerを使える技術者で揃えられればいいん
でしょうけど。それか教育ですかね(ニヤリ)
はじめまして、トピたてるまでもないかなと思ったので、
便乗質問させてください。

s2Dao(+s2Pager環境)でどのDAO componentに対しても、(j2ee.requiredTxなど)トランザクションタイプを指定しなければ、トランザクション機能を「使用しない」という認識であってますでしょうか。

DEBUGログには特に「トランザクションを〜」の文字は見つからなかったのですが、MySQLでクエリキャッシュが一切ヒットしなかったので、全てのクエリが自動的にトランザクションとして処理されているのかなぁと思ってしまいました。
(MySQLのmyISAMエンジンのクエリキャッシュはトランザクション内では使用できないのです。)

日本語おかしかったらすみません。
よろしくおねがいいたします。
>がちゃさん
>s2Dao(+s2Pager環境)でどのDAO componentに対しても、
>(j2ee.requiredTxなど)トランザクションタイプを指定しなけ
>れば、トランザクション機能を「使用しない」という認識で
>あってますでしょうか。

合ってると思います。
S2Daoでは、diconファイルで定義したクラスのメソッド
(全て、または一部)に対してアスペクトとしてトランザク
ションを発生させていますから、設定がされていなければトラ
ンザクションのアスペクト自体が発生しません。

個人的には、MyISAMのテーブルに対してトランザクションを
発生させたらどうなるんですかね?Exceptionがくるか、
スルーされるか・・・
自己レスです。

"S2Daoでは"と書きましたが、根本的にはS2AOPの話でしたね。
失礼しました。
>のぶさん、
ありがとうございます。そもそもありえないんですよね、MyISAMでトランザクション自体が。。(たぶん、commitやrollbackを発行した時点でSQL Exceptionが発生する気がします。)

以前からseasarを使わせていただいていたんですが、初めて自分でwebappを構築までする事になっていろいろ焦っておりました。

ログインすると、みんなのコメントがもっと見れるよ

mixiユーザー
ログインしてコメントしよう!

Seasar 更新情報

Seasarのメンバーはこんなコミュニティにも参加しています

星印の数は、共通して参加しているメンバーが多いほど増えます。