サポート > Wagby Developer Network > カスタマイズ事例 > アップロード一括更新の直後に、ストアド・プロシージャを呼び出す。

コード例

ここでは、Wagby の CSV アップロード一括更新の直後に、データベースのストアド・プロシージャを呼び出す事例を紹介します。 次のような動作を行うものとします。

  1. TemplateModel という名のモデルをアップロード一括更新する。この TemplateModel はワークモデル(一時的なモデル)という位置づけである。
  2. アップロード後、この TemplateModel を元に、モデル xxx を更新するストアドプロシージャを実行する。

修正するファイルは UploadUpdateTemplateModelProcessBean クラスです。今回、追加するコードの概要は次のとおりです。

  • TemplateModel データがアップロードされた際の初期化処理として、モデル xxx にロックを行う。
  • アップロードされた TemplateModel のデータを格納する前に「TemplateModel のデータを削除」と「TemplateModel のキャッシュをクリア」を行う。
  • アップロードされたデータが格納された後に「モデル xxx が格納されているテーブルに対して操作を行うストアドプロシージャの実行」「モデル xxx のキャッシュクリア」「モデル xxx のロック解除」を行う。

それでは以下、具体的なコードを使って説明します。

package jp.jasminesoft.wagby.app.TemplateModel;

import java.io.*;
...

import org.hibernate.*; // (1)
import jp.jasminesoft.jfc.app.HibernateUtil; // (1)

...

public class UploadUpdateTemplateModelProcessBean extends DbProcessBean
{
  ...
  /**
   * プロセスビーンを実行します。
   *
   * @return エラーメッセージ
   */
  @Override
  public Object run() {
    Logger logger = getLogger();
    StringBuilder errmsg = new StringBuilder();
    ...
    // UploadUpdateRunnableを作成する。
    FileInputStream istream = null;
    Reader reader = null;
    Connection connew = null;
    UploadUpdateRunnable monitor = null;

    try {
      // ファイルをオープンする。
      ...
      if (session_ != null) {
        lastaccesstime = session_.getLastAccessedTime();
      }
      monitor =
        new UploadUpdateRunnable(
          runnablep, reader, multi, lockobject, lastaccesstime);

      // カスタマイズ処理 (2) 開始
      // モデル xxx 内のデータをすべてロックする。
      String msg = monitor.registLockModelXxx((DbActionParameter)p);
      if (msg != null) {
        // ロック失敗時はエラーメッセージを返す。
        // よって、このメソッドはここで終了となる。
        return msg;
      }
      // カスタマイズ処理 (2) 終了

      // ヘッダーを読み込む
      try {
        monitor.readHeader();
      } catch (EOFException e) {
        // からのファイルを受信した場合
        logger.info("empty file "+file, e);
        monitor = null;
        ...
      }
    }
  }
  ...

  /**
   * 新規作成、更新の処理を行う Runnable
   */
  class UploadUpdateRunnable
    extends AbstractDbUploadUpdateRunnableMonitor
  {
    private final static int ErrorMessageCountLimit = 100;
    ...
    /**
     * コンストラクタ
     */
    public UploadUpdateRunnable(
      DbActionParameter p, Reader reader, MultiPartForm multi,
      LockObject lockobject, long lastaccesstime)
    {
      super();
      this.p = p;
      this.reader = reader;
      this.multi = multi;
      this.lockobject = lockobject;
      this.lastaccesstime = lastaccesstime;
      this.errorManager = BaseAction.getJFCErrorManager();
      this.errors = new Jfcerrors();
      this.targetSet = new HashSet(Arrays.asList(targetitems));
    }

    // カスタマイズ処理 (3) 開始
    private LockObject lockobject_modelxxx;

    /**
     * モデル xxx のデータをすべてロックするメソッドの定義。
     * カスタマイズ処理 (2) から呼び出される。
     */

    public String registLockModelXxx(DbActionParameter p1) {
      // ロックマネージャの準備
      LockManager lman = LockManagerFactory.getLockManager();
      LockObject lo = createLockObject(lman);

      LockObject _lo;
      if ((_lo = lman.addLockObject(lo)) == null) {
        // ロックに成功
        logger.debug(lo+" LockManager lock success.");
      } else {
        // ロックに失敗
        logger.warn(lo+" has already locked yet.");
        logger.debug("locked object is "+_lo);
        Object[] ep = { _lo.getUsername() };
        return errorManager.getJfcerror(
          "error.dbaccess.lock", ep, p1.locale).getContent();
      }
      lockobject_modelxxx = lo;
      return null;
    }

    /**
     * モデル xxx のデータをすべてロックするためのロックオブジェクトを
     * 作成する。
     */
    public LockObject createLockObject(LockManager lman) {
      final String modelname = "xxx";

      // モデル全体をロックする。
      // 実行したユーザがログアウトしても処理がバックグラウンドで
      // 実行されるので、セッションIDは "から文字" とする。
      String sessionid = "";
      LockObject lo =
        lman.createLockObjectForAll(modelname, sessionid, p.user);
      logger.debug("lo is "+lo);
      return lo;
    }

    /**
     * モデル xxx のロックを解除する。
     */
    public void releaseLockModelXxx() {
      // ロックマネージャの準備
      LockManager lman = LockManagerFactory.getLockManager();

      lman.releaseLockObject(lockobject_modelxxx);
      logger.debug(lockobject_modelxxx+" release lock.");
    }
    // カスタマイズ処理 (3) 終了


    /**
     * 処理開始時に呼び出される
     */
    protected void processStart() {
      p.user = p.user.referenceObject();

      // カスタマイズ処理 (4) 開始
      org.hibernate.Session session = HibernateUtil.openSession();
      Transaction tx = session.beginTransaction();

      try {
        // オブジェクト TemplateModel を削除します。
        // 以下の [1] [2] のいずれかを有効にして使ってください。
        // [1] チェックボックスや繰り返し項目がある場合は、以下を
        // 有効にしてください。
        /*
        String expression1 = "from TemplateModel";
        Query query1 = session.createQuery(expression1);
        ScrollableResults results = query1.scroll();
        while (results.next()) {
          Object obj = results.get(0);
          session.delete(obj); // すべての結果を削除する。
        }
        */

        // [2] 繰り返しコンテナを含むモデルの場合は、以下を
        // 有効にしてください。
        /*
        String expression2 =
          "delete from jp.jasminesoft.wagby.model.TemplateModel.Cont";
        Query query2 = session.createQuery(expression2);
        int num2 = query2.executeUpdate();
        logger.debug(expression2+" "+num2);

        // 最後に大元となるクラスを削除します。
        String expression3 = "delete from TemplateModel";
        Query query3 = session.createQuery(expression3);
        int num3 = query3.executeUpdate();
        logger.debug(expression3+" "+num3);
        */

        tx.commit();

        // キャッシュマネージャを利用します。
        jp.jasminesoft.wagby.app.CacheManager cman =
          jp.jasminesoft.wagby.app.CacheManager.getInstance(p);
        cman.clearTemplateModel();
        HibernateUtil.unbindCurrentSession();

        JFCDataAccessManager dam =
          (JFCDataAccessManager)p.appctx.getBean(
            "JFCDataAccessManager");

        if (dam == null) {
          logger.error("failed get JFCDataAccessManager");
        } else {
          dam.clearCountAll((DbActionParameter)p);
        }
      } catch (Exception e) {
        // エラー処理
        logger.warn("failed delete from TemplateModel", e);
        throw new IllegalStateException();
      } finally {
        StringBuilder debugmsg = new StringBuilder();
        debugmsg.append("finally delete from TemplateModel");
        logger.debug(JFCUtils.logmsg(p, debugmsg.toString()));
        // セッションを閉じます。
        session.close();
      }
      // カスタマイズ処理 (4) 終了

    }

    /**
     * 処理終了時に呼び出される
     */
    protected void processEnd() {

      // カスタマイズ処理 (5) 開始
      // ストアドプロシージャを実行します。
      java.sql.CallableStatement cstmt = null;
      java.sql.ResultSet rset = null;

      try {
        // ストアド・プロシージャ PROC を呼び出して
        // モデル Xxx を更新します。
        String proc = "PROC('arg')";
        String call = "{call " + proc + "}";
        cstmt = p.con.prepareCall(call);
        rset = cstmt.executeQuery();
        p.con.commit();
      } catch (Exception e) {
        // エラー処理
        logger.warn("failed call stored procedure PROC('arg')", e);
      }

      // キャッシュマネージャを利用します。
      jp.jasminesoft.wagby.app.CacheManager cman =
        jp.jasminesoft.wagby.app.CacheManager.getInstance(p);
      cman.clearXxx();

      HibernateUtil.unbindCurrentSession();

      JFCDataAccessManager dam =
        (JFCDataAccessManager)p.appctx.getBean(
          "JFCDataAccessManager");
      if (dam == null) {
        logger.error("failed get JFCDataAccessManager");
      } else {
        dam.clearCountAll((DbActionParameter)p);
      }

      // モデル xxx のロックを解除する。
      releaseLockModelXxx();

      // カスタマイズ処理 (5) 終了


      // コネクションを閉じる
      try {
        p.con.close();
      } catch (SQLException e) {
        logger.warn("failed close connection", e);
      }
      ...
    }
    ...
  }
  ...
}

カスタマイズを行った部分には、コメントを記しています。ロックの取得と解放、キャッシュのクリアが適切に行われていることを確認してください。

このページ

カスタマイズ事例