- PR -

DataSourceコネクションのAutoCommit設定について

投稿者投稿内容
Hyde
ベテラン
会議室デビュー日: 2005/05/18
投稿数: 63
投稿日時: 2005-06-24 16:49
いつもお世話になっています。

JBOSSのデータソースを利用して、トランザクションを使いたいのですがAUTOコミットをOFFにしようとすると以下のような例外が発生します。この解決策を探っているのですがどなたか分かる方がいらっしゃいましたら、ご教授願います。
データベースはオラクルを使っています。

■コード
ds = (DataSource)context.lookup(DSNAME);
// DataSourceからDBコネクション情報を取得
Connection conn = ds.getConnection(); // ここまでは正常に取得できています。

// オートコミット設定
conn.setAutoCommit(false);

■ログ


2005/06/24 15:47:16.892 ERROR [fec.telegram.control.AbstractFosMsgAnalyze:analyze:138] java.sql.SQLException: You cannot set autocommit during a managed transaction!
at org.jboss.resource.adapter.jdbc.BaseWrapperManagedConnection.setJdbcAutoCommit(BaseWrapperManagedConnection.java:468)
at org.jboss.resource.adapter.jdbc.WrappedConnection.setAutoCommit(WrappedConnection.java:443)
at fec.telegram.control.AbstractFscpMsgAnalyze.connectDB(AbstractFscpMsgAnalyze.java:109)
at fec.telegram.control.AbstractFosMsgAnalyze.analyze(AbstractFosMsgAnalyze.java:81)
at fec.sb.fos2fec.Fos2FecBean.sub_execute(Fos2FecBean.java:206)
at fec.sb.fos2fec.Fos2FecBean.execute(Fos2FecBean.java:165)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invoke(StatelessSessionContainer.java:683)
at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionInterceptor.java:185)
at org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invoke(StatelessSessionInstanceInterceptor.java:72)
at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:84)
at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:315)
at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:148)
at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:120)
at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:191)
at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:122)
at org.jboss.ejb.StatelessSessionContainer.internalInvoke(StatelessSessionContainer.java:331)
at org.jboss.ejb.Container.invoke(Container.java:723)

■環境は、
JBOSS 3.2.5
eclipse 3.01
j2sdk 1.4.2._08

使用しているオラクルのドライバは classes12.jar
設定ファイルはoracle-ds.xmlだけあわせました。


ちなみに、oracle-ds.xmlにはAUTOコミットの設定箇所とかは、やりかたがあるのかわからないので、してないのですが、どこかの設定する箇所がありますでしょうか?

また、そもそも、AUTOCOMMITてコネクションプーリング使いたいときにはOFFにできないとか、そんな事情があったりしますでしょうか。

よろしくおねがいします。
takashi
ベテラン
会議室デビュー日: 2004/02/12
投稿数: 79
お住まい・勤務地: 東京
投稿日時: 2005-06-24 16:56
>You cannot set autocommit during a managed transaction!

このメッセージを見る限り、トランザクションが開始してからAUTOCOMMITを変更できないといっていますね。
考えてみればそのとおりで、まずJBOSSなどのアプリケーションサーバではトランザクションはコンテナでの制御になるのでAUTOCOMMITを明示的に変更する必要はないのではないでしょうか?

以上予想で言ってますので、何かの参考になれば。
Hyde
ベテラン
会議室デビュー日: 2005/05/18
投稿数: 63
投稿日時: 2005-06-24 17:19
takashiさん
レスありがとうございます。

「必要ない」といわれてしまうと困ってしまう(笑)のですが。。。
制御したい理由はあるにはあるのです。

今回開発しているアプリではCMPやBMPは特に使っておりません。
DBの利用に関してシステムの要求するものが今回
@レスポンスの速さと
Aプーリングの利用
だったのですが、DataSourceを使用するにあたってコンテナで管理される状況がいまいち理解できておりません。。。(内部ではどのような処理になっているのでしょうか。)

たとえば数本のSQLを走らせて、まとまった処理が成功したときのみコミットをかけたいのですが、そういった制御は、JBOSSのデータソースを利用してできないものなのでしょうか?

コンテナに制御を任せた場合、SQLの発行の度に問答無用でコミットされてしまうのでしょうか。。。



takashi
ベテラン
会議室デビュー日: 2004/02/12
投稿数: 79
お住まい・勤務地: 東京
投稿日時: 2005-06-24 17:38
えーと、まずコネクションプーリングとAUTOCOMMITを分けて考える必要があると思います。

>@レスポンスの速さと
>Aプーリングの利用

この二つに関してですが、@を実現するためにAがあるのだと思います。
DataSourceを使用することにより、複数のコネクションをプールしておき、クライアントが必要なときにそのプールからコネクションを取得することでDB接続のコストを抑えレスポンスが向上されます。
プールしておくコネクションの最大数やタイムアウト設定はJBOSSの場合*-service.xmlとかの設定ファイルで可能だったと記憶してます。

次にトランザクションのコンテナ制御ですが、こちらはejb-jar.xmlなどで設定していると思います。
<assembly-descriptor>部の<container-transaction>要素でトランザクションの指定ができます。
そして、SQL発行の度にコミットが行われるわけではなく、SessionBeanのあるメソッドにてSQL発行処理を行っているのであれば、そのメソッドが正常終了すればコミット、以上終了(例外など)すればロールバックといった制御が可能だったと思います。

JBOSSの情報でしたら、JBoss入門(技術評論社)がとても詳しく解説してますのでそちらを参考にされてはいかがでしょうか?
Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2005-06-24 18:10
おそらくEJB(SLSB)を利用しているんですよね?その前提で書きます。
JTA境界内で呼び出したXA対応のJDBCリソースのConnectionのAutoCommitをfalseにすることはできません。これはJ2EEの仕様です。
コミットですがEJBを利用しているのであればトランザクション境界を正常に出れば自動的にコミットされます。
細かくコミットしたいのであれば、トランザクション属性をRequiresNewとしたメソッドを作成するなどしてください。でなければトランザクション属性をSupportsなどにしてautocommitをfalseにして処理を行うかです。
ただしこの場合はEJBを利用するメリットはほぼゼロになりますが・・・。
Hyde
ベテラン
会議室デビュー日: 2005/05/18
投稿数: 63
投稿日時: 2005-06-24 20:58
takashiさん、Anthyhimeさん、レスありがとうございます。
ところで、早速なのですが、ムズイです。。。やりたいことははっきりしてるのに、設定箇所がわかりません。ちょうどレスがあったころ、データソースだけでもだめで、UserTransactionを使うべきなのだ。。。ということに気づいたころなのですが、そのまま

ut = (UserTransaction)context.lookup("java:comp/UserTransaction");

とやっても
UserTransactionの生成に失敗します。
そこで、このJNDI名を設定するところはどこなのだ。。。と調べてみたのですが、Tomcatの設定の仕方は探し出せてもJBOSSの場合の設定の仕方が分からないのです。。。

どのXMLにどんなタグの設定をすべきなのか?が現在のテーマとなってまいりました。

<アドバイスの件でやってみたこと>
*-service.xmlもたくさんあって、とりあえず、Transaction-service.xml に
以下のような記述をしてみたのですが、だめでした。。。

<mbean code="org.jboss.jdbc.XADataSourceLoader" name="DefaultDomain:service=XADataSource,name=OracleDS">
<attribute name="PoolName">OracleDS</attribute>
<attribute name="DataSourceClass">org.jboss.pool.jdbc.xa.wrapper.XADataSourceImpl</attribute>[JBoss 3.2]
<attribute name="URL">jdbc:oracle:thin:@xxx.xx.2.50:1521:fmjwatch</attribute>
<attribute name="JDBCUser">fmjwatch</attribute>
<attribute name="Password">fmjwatch</attribute>
</mbean>

そこで、本当はTomcatの
<server.xml(抜粋)>

<Resource auth="Container" name="UserTransaction" type="javax.transaction.UserTransaction"/>
<ResourceParams name="UserTransaction">
<parameter>
<name>jotm.timeout</name>
<value>60</value>
</parameter>
<parameter>
<name>factory</name>
<value>org.objectweb.jotm.UserTransactionFactory</value>
</parameter>
</ResourceParams>

に相当するJBOSSの設定をしてみたいのですが、
担当するXMLが変わってしまっているようで、わからない状態です。


Anthyhimeさんのアドバイスの件なのですが、それをやってしまうとCMPになってしまいますよね。。。通常のDataBaseManagerの接続をDataSource接続にしたいだけなのですが、エンティティビーンとか使わないとだめですかね。。。その場合、自分はいまstatelessなセッションビーンの内部で使用しているのですが、xDocletタグの追加だけでいけるものでしょうか?まったく変えないといけないでしょうか。。。

すみません、けっこうはまってます。
よろしくお願いいたします。

uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-06-24 22:59
セッションBeanの内部であれば、そのメソッド内で実行したデータベースアクセスはひとつの
トランザクションとして実行されます。したがってトランザクションとしてまとめたい処理が
ひとつのメソッド内で実行されていればいいはずですが、メソッドにまたがるトランザクションを
実行したいということでしょうか。
Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2005-06-24 23:03
JNDI名はそれであってます。
おそらくUserTransactionをうまく設定しても、JTAは標準ではネストされたトランザクションをサポートしないのでEJB内でUserTransactionを取得してトランザクション管理しようとしてもうまくいかないでしょう。

> Anthyhimeさんのアドバイスの件なのですが、それをやってしまうとCMPになってしまいますよね

EntityBeanではないのでCMPやBMPとは関係がありません。
メソッドのトランザクション属性を変更してJTAオフの状態でDataSourceからConnectionを取得してくださいといっているだけです。
おそらくそれでautocommitをfalseに設定できるはずです。

スキルアップ/キャリアアップ(JOB@IT)