- PR -

テーブル更新処理を全件終えた後にコミットしたい

投稿者投稿内容
ぬべたそ
ベテラン
会議室デビュー日: 2003/12/18
投稿数: 72
投稿日時: 2005-04-22 16:02
HibernateやS2はほとんど分からないので、もう確認済みでしたらご容赦下さい。

データベースにmysqlを利用しているようですが、これはトランザクション制御をできるように設定されていますか?たしか、InnoDBとかそんな名称だったと思いますが。

フレームワークなどを使わずに単純なアプリケーションでデータベースの更新、ロールバックは行えるのでしょうか?

たまこ
常連さん
会議室デビュー日: 2005/01/12
投稿数: 25
投稿日時: 2005-04-22 17:36
taiping様
ご指導ありがとうございます。
MySQLのテーブルタイプはInnoDBで作成しています。
コマンドラインにおけるトランザクション操作ですが、
set autocommit=0 としてcommit、rollbackの確認はしています。

フレームワークを使うことによって、こういうところで悩むとは思ってもいませんでした。
こんな処理、フレームワークなしのJavaアプリやCなら簡単にできるのに・・・。
すっかり路頭に迷ってしまいました。
明示的なトランザクション管理のが「楽」と自分が言っているのは、
きっと今だけのことなんでしょうけど・・・。

ところで現在、log4jでDEBUGレベルのログを出力させていますが、
「トランザクションを開始しました」とか「トランザクションをコミットしました」とか、そのようなメッセージが出てきません。
普通出てくるものなのでしょうか・・・?

もし必要なソースがあれば載せますので、ご指導よろしく願い致します。
Odakaz
ベテラン
会議室デビュー日: 2004/05/24
投稿数: 70
投稿日時: 2005-04-22 18:03
私も最近、Seasar2とS2Hibernateを試していますが、特にこういう事象はないですね・・・。
#トランザクションはSeasar2にまかせきりです。

ともあれ、最初からだいぶソース等も変わっているみたいですし、整理の意味も含めてもう一度、関連ファイルをここに提示されてはいかがでしょうか?
たまこ
常連さん
会議室デビュー日: 2005/01/12
投稿数: 25
投稿日時: 2005-04-22 18:13
>>Odakazu様

ありがとうございます。
もう一度、関連ソースを載せますので、
どうぞよろしくお願いします。
たまこ
常連さん
会議室デビュー日: 2005/01/12
投稿数: 25
投稿日時: 2005-04-22 19:47
再びたまこです。(200行以上の長い書き込みになります。)
最新のソースを載せます。
・s2xwork.xml
・j2ee.dicon
・dicontainer.xml
・s2Hibernate.dicon
・HogeAction.java
・HogeDAO.java
・DAOUtil.java

HogeDAOでExceptionを投げ、HogeActionがcatchします。
TransactionはHogeActionで新しいTransactionを開始し、
HogeDAOでは開始されていない場合エラーとします。
Exceptionが発生すると、全体のrollbackになり、
それまでに更新されたUserTblのAgeもrollbackされることを想定してます。
がしかし、現在はExceptionが発生されても、データの更新がされてしまいます。

先ほども書きましたが、log4jのDEBUGレベルのログで、
トランザクション関連のログが出てきません。
(トランザクションを開始します、トランザクションをコミットします、など。)
それが何か関係ありそうだと目を付けているところです。

申し訳ありませんが、何かお気づきの点がありましたら、ご教授・アドバイスをお願い致します。

(なお、xmlのヘッダや各種Exceptionなどは割愛させて頂きます。)

=== s2xwork.xml ====================================
<components>
 <include path="j2ee.dicon"/>
 <include path="dicontainer.xml"/>
 <include path="s2Hibernate.dicon"/>
 <component class="org.seasar.hibernate.impl.S2SessionFactoryImpl"/>
 <component name="sessionFactory" class="org.seasar.hibernate.impl.S2SessionFactoryImpl"/>
 <component name="traceInterceptor"
  class="org.seasar.framework.aop.interceptors.TraceInterceptor"/>
 <component name="hogedao" autoBinding="none" class="hoge.dao.HogeDAO">
  <aspect pointcut="updUser">j2ee.mandatoryTx</aspect>
  <aspect>traceInterceptor</aspect>
  <property name="sessionFactory">sessionFactory</property>
 </component>
 <component instance="prototype" autoBinding="none" class="hoge.HogeAction">
  <aspect pointcut="execute">j2ee.requiresNewTx</aspect>
  <property name="hogeDAO">hogedao</property>
 </component>
</components>
====================================================

=== j2ee.dicon =====================================
<components namespace="j2ee">
 <component name="transactionManager"
  class="org.seasar.extension.jta.TransactionManagerImpl"/>
 <component name="requiredTx"
  class="org.seasar.extension.tx.RequiredInterceptor"/>
 <component name="requiresNewTx"
  class="org.seasar.extension.tx.RequiresNewInterceptor"/>
 <component name="mandatoryTx"
  class="org.seasar.extension.tx.MandatoryInterceptor"/>
 <component class="org.seasar.extension.jdbc.impl.BasicResultSetFactory"/>
 <component class="org.seasar.extension.jdbc.impl.BasicStatementFactory"/>
 <component name="xaDataSource"
  class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
  <property name="driverClassName">"org.gjt.mm.mysql.Driver"</property>
  <property name="URL">"jdbc:mysql://localhost/hoge"</property>
  <property name="user">"hoge"</property>
  <property name="password">"****"</property>
 </component>
 <component name="connectionPool"
  class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl">
  <property name="timeout">600</property>
  <property name="maxPoolSize">64</property>
  <destroyMethod name="close"/>
 </component>
 <component name="dataSource"
  class="org.seasar.extension.dbcp.impl.DataSourceImpl"/>
</components>
=====================================================

=== dicontainer.xml =================================
<components namespace="dicontainer">
 <component name="s2container" class="org.seasar.framework.container.S2Container" >
  <arg>container</arg>
 </component>
</components>
=====================================================

=== s2Hibernate.dicon ===============================
<components namespace="s2hibernate">
 <include path="j2ee.dicon"/>
 <component class="org.seasar.hibernate.impl.S2SessionFactoryImpl"/>
 <component class="org.seasar.hibernate.dao.impl.HibernateDaoMetaDataFactoryImpl"/>
 <component name="interceptor"
  class="org.seasar.hibernate.dao.interceptors.S2HibernateDaoInterceptor"/>
</components>
=====================================================

以下はJavaソースです。
(Exceptionは種類が多いので割愛させて頂きます。)
・画面から遷移するアクションがHogeAction.java
・HogeAction.javaのexecuteメソッドから呼び出されるDAOがHogeDAO.java
・コンテナの操作やdiconファイルの読み取りはDAOUtilで行います。

=== HogeAction.java =================================
package hoge.action;

import java.io.File;
import com.opensymphony.xwork.Action;
import com.opensymphony.xwork.ActionSupport;
import org.apache.log4j.Logger;
import hoge.dao.HogeDAO;

public class HogeAction extends ActionSupport implements Action{
 private static final Logger log = Logger.getLogger(HogeAction.class);
 private String[][] warr;
 private int lineCnt = 3;
// セッターゲッターは割愛
 public HogeAction(){
 }
 public String execute(){
  warr = new String[lineCnt][10];
  if (warr != null){
   HogeDAO hogedao = new HogeDAO();
   boolean ret;
   try {
    // 更新処理
    ret = hogedao.updUser(warr,lineCnt);
   } catch (〜〜Exception 〜〜e){
    log.error(〜〜e.getCause());
    log.info("異常終了");
    return INPUT;
   }
  }
  log.info("正常終了");
  return SUCCESS;
 }
}
=====================================================

=== HogeDAO.java =================================
package hoge.dao;

import org.seasar.hibernate.S2SessionFactory;
import org.seasar.hibernate.S2Session;
import java.util.List;
import net.sf.hibernate.Hibernate;
import hoge.dao.DAOUtil;
import hoge.entity.UserTbl;

public class HogeDAO{
 /** コンストラクタ **/
 public HogeDAO() {}
 /** 使用するS2SessionFactory */
 public S2SessionFactory factory;
 public void setSessionFactory(S2SessionFactory factory) {
  this.factory = factory;
 }
 public boolean updUser(String[][] warr,int lineCnt) throws 〜〜Exception{
  int i,j;
  UserTbl im = new UserTbl();
  DAOUtil du = new DAOUtil();
  du.setUp();
  HogeDAO hogedao = du.getDAO();
  factory = (S2SessionFactory) du.getSessionFactory();
  S2Session session = factory.getSession();
  // 配列の箱分繰り返し
  for (j = 0 ; j < lineCnt-1 ; j++){
   for (i = 0 ; i < 10 ; i++){
    if (j == lineCnt-2 && warr[j][i]== null){
     session.flush();
     return true;
    }
    // 該当データが存在するか検索
    List result = session.find("from UserTbl as u where u.userId = ?",warr[j][i],Hibernate.STRING);
    if (result.size() > 0) {
     usertbl = (UserTbl) result.get(0);
    } else {
     throw new Exception("エラーメッセージ");
    }
    // 現在の年齢に1足した数で更新します
    int userAge = usertbl.getAge() + 1;
    usertbl.setAge(userAge);
    session.update(usertbl);
    i++;
   }
   j++;
  }
  session.flush();
  return true;
 }
}
=====================================================

=== DAOUtil.java =================================
package hoge.dao;

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

public class DAOUtil{
 private String diconPath = "s2xwork.xml";
 protected S2Container container;
 protected void setDiconPath(String diconPath){
  this.diconPath = diconPath;
 }
 public void setUp(){
  container = S2ContainerFactory.create(diconPath);
 }
 public HogeDAO getDAO(){
  return (HogeDAO)container.getComponent(HogeDAO.class);
 }
 public Object getSessionFactory(){
  return container.getComponent("sessionFactory");
 }
 protected Object getComponent(Class type){
  return container.getComponent(type);
 }
 protected Object getComponent(String name){
  return container.getComponent(name);
 }
=====================================================

Odakaz
ベテラン
会議室デビュー日: 2004/05/24
投稿数: 70
投稿日時: 2005-04-22 22:35
私も、2日ほど前からいじり始めたばかりで、トランザクションもDAOで使っているだけなので、推測というかあてずっぽうに近いのですが・・・
HogeActionにおいて、
引用:

   } catch (〜〜Exception 〜〜e){
    log.error(〜〜e.getCause());
    log.info("異常終了");
    return INPUT;
   }


ここで例外を握りつぶしているように見えますが、これだとコミットされてしまわないでしょうか?

HogeActionでトランザクションを開始しているように見えるので、ここで例外を握りつぶすと、そういう挙動になるのかなぁと思いまして・・・。

[ メッセージ編集済み 編集者: Odakaz 編集日時 2005-04-22 22:48 ]
Odakaz
ベテラン
会議室デビュー日: 2004/05/24
投稿数: 70
投稿日時: 2005-04-22 23:17
あと、スレッドの最初の方でAnthyhimeさんが仰っていたように、ここまでのトランザクション処理は要らないかもしれませんね。
DAOの中だけで完結しそうに思えます。
たまこ
常連さん
会議室デビュー日: 2005/01/12
投稿数: 25
投稿日時: 2005-04-23 23:15
Odakazさま
何度もご教授ありがとうございます。

> あと、スレッドの最初の方でAnthyhimeさんが仰っていたように、ここまでのトランザクション処理は要らないかもしれませんね。

確かにトランザクションが必要なのは、DAO部分のみですね。
そうなると、HogeActionのaspect pointcutをなくし、HogeDAOのメソッドのaspect pointcutをrequiresNewTxにすることで、そのメソッド内のみのトランザクション制御が行えるかと思い、実行してみました。
しかし、やはりテーブルデータはcommitされてしまい、うまくいきません。。

Odakazさんはlog4jを使っていらっしゃいますか?
DEBUGログにトランザクションの開始・コミット・ロールバックなどのログは出ますか?
私のログにはそれが出てきません。
何が違うのでしょう。。
トランザクションに関するログは、以下の1行しか出ません。

2005-04-23 22:37:38,466 INFO net.sf.hibernate.transaction.TransactionManagerLookupFactory - No TransactionManagerLookup configured (in JTA environment, use of process level read-write cache is not recommended) [http-8080-Processor24] (TransactionManagerLookupFactory.java:33)

hibernate.cfg.xmlには、
<class-cache usage="read-write" class="hoge.entity.UserTbl" />
と記述しています。

すみません、何か手がかりがありましたら、教えてください。。

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