JdbcDaoSupportを継承したDaoAImpl、DaoBImplクラスがあり、DaoCImplで
A、Bの順にインターフェースを介してインスタンス化し、その順にそれぞれ
更新処理を走らせた時にDaoBImplでエラーが起こった場合、DaoAImplの更新処理を
ロールバックさせたいと思いますが現在DaoAImplの処理がコミットされてしまいます。
Testが実行クラスで、以下に現在の実装を記します。※ここではDBUtilsを使用
◆DAO(DaoBは同じ内容なので省略)
--------------------------------------------------------------
public class DaoAImpl extends JdbcDaoSupport implements DaoA {
/** DBコネクション */
private Connection con = null;
/** update */
public void execute(String sql) throws SQLException {
if (null == con) con = super.getConnection();
// 更新
QueryRunner qr = new QueryRunner();
qr.update(con, sql);
}
}
--------------------------------------------------------------
public class DaoCImpl implements DaoC {
/** update */
public void double_execute() throws SQLException {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
BeanFactory factory = (BeanFactory) context;
DaoA a = (DaoA) factory.getBean("daoA");
DaoB b = (DaoB) factory.getBean("daoB");
a.execute("UPDATE A_TABLE SET FLG = 2");
b.execute("UPDATE A_TABLE SET FLG = 3");
}
}
--------------------------------------------------------------
public class Test {
/** main */
public static void main(String[] args) throws Exception {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
BeanFactory factory = (BeanFactory) context;
DaoC c = (DaoC) factory.getBean("daoC");
c.double_execute();
}
}
--------------------------------------------------------------
◆applicationContext.xml
--------------------------------------------------------------
~中略~
<!-- Transaction -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource"><ref local="dataSource"/></property>
</bean>
<bean id="txAttribute" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
<property name="properties">
<props>
<prop key="*execute">PROPAGATION_REQUIRES_NEW, -SQLException</prop>
<prop key="select*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id="txInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="transactionAttributeSource"><ref bean="txAttribute"/></property>
</bean>
<bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<idref local="txInterceptor"/>
</list>
</property>
<property name="beanNames">
<list>
<value>dao*</value>
</list>
</property>
</bean>
<bean id="daoA" class="DaoAImpl">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<bean id="daoB" class="DaoBImpl">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<bean id="daoC" class="DaoCImpl">
</bean>
</beans>
--------------------------------------------------------------
以上、お手数ですがご指摘お願い致します。
No.4ベストアンサー
- 回答日時:
QueryRunnerはorg.apache.commons.dbutils.QueryRunnerでしょうか?
トランザクション処理を実行するクラスにSpringを
使用していないので、当然宣言的トランザクションは実現できません。
org.springframework.jdbc.object.SqlUpdateを継承した
RDBMSオペレーションクラスを作成し、本クラスのupdateメソッドに
SqlParameterクラスでパラメータを指定して
トランザクション処理を実行します。
【サンプル】
----------------------------------------------
private static class InsertOwnerQuery extends SqlUpdate {
private static final String SQL_INSERT
= "insert into OWNER(OWNER_ID, OWNER_NAME) values(?, ?)";
private InsertOwnerQuery(DataSource ds) {
super(ds, SQL_INSERT);
super.declareParameter(new SqlParameter("ownerId", Types.VARCHAR));
super.declareParameter(new SqlParameter("ownerName", Types.VARCHAR));
}
// 挿入処理のヘルパーメソッド
private int insert(String ownerId, String ownerName) {
Object[] param = {ownerId, ownerName};
return update(param);
}
}
-------------------------------------------------
XMLの設定に関しては、SQLException発生時にRollbackする設定を
されているようですので、発生させる例外がSQLExceptionであれば
問題なくRollbackされるはずです
(念の為、XMLには、java.sql.SQLExceptionとしておいて方がいいかも)。
後は前回指摘したようにPROPAGATION_REQUIREDを設定すれば大丈夫だと思います。
度々のご返信、誠にありがとうございます。
ご指摘の内容を検証させて頂きましたが結果は同じでした。
当方でも色々調べました結果、DaoA及びDaoBとDaoCを別々で新規生成した
ApplicationContextオブジェクトから取得していたのを、DaoCを取得した時点で
DaoA、DaoBもインジェクションされるようにapplicationContext.xmlとDaoCImplを
以下のように修正しました所、当初の想定の動きになりました。
ApplicationContext毎にAutoProxyの管理が行われているような感じがします。
◆1.applicationContext.xml
<bean id="daoC" class="DaoCImpl">
<property name="daoA">
<ref bean="daoA"/>
</property>
<property name="daoB">
<ref bean="daoB"/>
</property>
</bean>
◆2.DaoCImpl 追加コード
private DaoA daoA = null;
private DaoB daoB = null;
public DaoA getDaoA() { return daoA; }
public void setDaoA(DaoA daoA) { this.daoA = daoA; }
public DaoB getDaoB() { return daoB; }
public void setDaoB(DaoB daoB) { this.daoB = daoB;}
◇参考URL
http://static.springframework.org/spring/docs/2. …
※BeanPostProcessors and AOP auto-proxyingの項
Bean 'autoProxyCreator' is not eligible for getting processed
by all BeanPostProcessors (for example: not eligible for auto-proxying)
No.3
- 回答日時:
> コネクションを
> DaoCImplのみで取得して...
そうすると、私の最初の回答のように、単一のトランザクションスコープになりますよね?。(想像ですが)
XMLのレベルでなく、あくまでもプログラムのレベルで検討してください!。
No.2
- 回答日時:
applicationContext.xmlに
「PROPAGATION_REQUIRES_NEW」を指定しているのが原因と思われます。
上記を指定すると新たなトランザクションを開始してしまいます。
PROPAGATION_REQUIREDなどを指定すると、トランザクションが開始されていれば同一トランザクションで実行するように動作します。
詳しくは参考URLを見てみてください。
参考URL:http://www.techscore.com/tech/Others/Spring/6.html
ご指摘ありがとうございます。以下のようにPROPAGATION_REQUIREDを指定しても結果は同じでした。
<prop key="*execute">PROPAGATION_REQUIRED, -SQLException</prop>
念の為、合わせて以下のように記述するとDaoAImpl、DaoBImpl両方の処理がコミットされました。
<property name="beanNames">
<list>
<value>daoC</value>
</list>
</property>
現在DaoAImpl、DaoBImplのコミットが独立して行われているような感じですので、コネクションを
DaoCImplのみで取得してDaoAImpl、DaoBImplではJdbcDaoSupportを継承やコネクションを取得したりせず
DaoCImplから引数としてコネクションを渡して処理をさせると、想定通り両方の処理がロールバックされる事は確認しています。
よく分かりませんがJdbcDaoSupportを継承したクラス単位で管理されているような印象です。
No.1
- 回答日時:
詳細はよく見えませんが、二つの処理が一つのトランザクション管理スコープ内に包まれていないのではないですか。
一つのトランザクション管理スコープとは、単純化して例示すると:
try{
con.setAutoCommit(false);
...
...
...
con.commit();
}
catch (.....){
con.rollback();
}
etc., etc.
ご返信ありがとうございます。DaoCImplのdouble_executeが正常終了すると
トランザクションがコミットされるようにapplicationContext.xmlで
指定したつもりがうまくいっていない状況です。
クラスが悪いのか設定が悪いのかどっちも悪いのか謎です。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・ちょっと先の未来クイズ第4問
- ・【大喜利】【投稿~10/21(月)】買ったばかりの自転車を分解してひと言
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・ハマっている「お菓子」を教えて!
- ・最近、いつ泣きましたか?
- ・夏が終わったと感じる瞬間って、どんな時?
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・都道府県穴埋めゲーム
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
オブジェクトの中のプロパティ...
-
JSPでImportエラーになります
-
JSPからServletに、テーブルに...
-
Java Struts ~に対するゲッタ...
-
StrutsでJSPからListを受け取り...
-
hiddenの値が期待した値で取得...
-
ログイン画面
-
データベース接続について。
-
同時アクセス時の動作
-
androidアプリが強制終了してし...
-
System.err. printlnとSystem.o...
-
ダブルクォーテーションのrepla...
-
IF関数でEmpty値を設定する方法。
-
Javaで改行などが出来ないのです。
-
JSPやサーブレットでSystem.out...
-
パソコンキーボードで時分秒を...
-
[Ljava.lang.Stringってなんですか
-
ダブルクォーテーションを含む...
-
sin曲線とcos曲線を描くプログ...
-
C言語のポインターに関する警告
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
オブジェクトの中のプロパティ...
-
StrutsでJSPからListを受け取り...
-
JSPでImportエラーになります
-
hiddenの値が期待した値で取得...
-
JSPからServletに、テーブルに...
-
<s:iterator>の値をリストで取...
-
requestの値が削除されません…
-
Java Struts ~に対するゲッタ...
-
【Struts】bean:writeタグのpro...
-
iterateで受け取った値を処理に...
-
JSPでDBからデータ読み込みブラ...
-
PropertyNotFoundException解決...
-
【struts】 ActionFormで別のAc...
-
JSPにて、変数を利用してフォン...
-
JSFタグ<h:dataTable>でヘッダ...
-
Struts2 selectタグのmultiple...
-
DOMでXMLからデータを抽出する...
-
データベースに変数の値を挿入
-
全取得したデータをjspで順番に...
-
java strutsでの一覧表の表示方...
おすすめ情報