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で質問しましょう!
似たような質問が見つかりました
- Java java final 1 2022/06/10 22:49
- HTML・CSS ボタンをクリックした時に、入力フォームのすぐ下部に、「入力欄が空白です」というテキストメッセージが表 1 2022/04/27 16:25
- JavaScript sessionStorageを調べています。 1 2023/06/20 12:41
- HTML・CSS CSS のみのタブ切り替えについて 1 2023/01/11 16:47
- JavaScript 入力フォームの javascript で メールアドレスの正規チェックをを行い、ボタンをクリックして 2 2022/04/27 16:06
- Java java 入力 3 4 3 出力 ABC DEFG HIJ このようなプログラムの書き方を教えてくだ 2 2022/07/15 14:18
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- JavaScript javascriptで移動ボタンを押した際に遷移するボタンを追記したい 1 2022/11/29 03:02
- FX・外国為替取引 mql4のコンパイルエラー箇所の修正お願いします。 1 2023/03/15 16:14
- JavaScript jqueryを使ったスムーススクロールのコードを書いたのですが、HTMLコード内にある、a butt 2 2022/04/14 10:59
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
オブジェクトの中のプロパティ...
-
PropertyNotFoundException解決...
-
JSPにて、変数を利用してフォン...
-
ラジオボタンを使って更新 ecl...
-
iterateで受け取った値を処理に...
-
困ってます
-
JSPでImportエラーになります
-
C言語のポインターに関する警告
-
JSPやサーブレットでSystem.out...
-
[JAVA]try 内の変数を外で!?
-
1~100までの数字を表示したい
-
VBで作った乱数を一度も重複さ...
-
数値⇒漢数字変換 java
-
flush()とclose()について
-
1~100までの数字を表示し、か...
-
EclipseでJava
-
javaで質問です。 文字列2023/2...
-
0dの意味を教えてください
-
Javaで改行などが出来ないのです。
-
ファイル名に変数を使う(Java)
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
オブジェクトの中のプロパティ...
-
JSPでImportエラーになります
-
hiddenの値が期待した値で取得...
-
StrutsでJSPからListを受け取り...
-
requestの値が削除されません…
-
Java Struts ~に対するゲッタ...
-
PropertyNotFoundException解決...
-
全取得したデータをjspで順番に...
-
<s:iterator>の値をリストで取...
-
JSPにて、変数を利用してフォン...
-
JSPでDBからデータ読み込みブラ...
-
データベースに変数の値を挿入
-
No such validation エラー
-
JSPからServletに、テーブルに...
-
iterateで受け取った値を処理に...
-
StrutsのforEachについて
-
JSFタグ<h:dataTable>でヘッダ...
-
サーブレットjspで勤怠スケジュ...
-
javaの環境変数の%CATALINA_HOM...
-
WebWork(struts2)でのパラメー...
おすすめ情報