• ベストアンサー

トランザクション管理について

皆さんはトランザクション管理を何処で行ってますか? 大体のプロジェクトでは以下の2パターンに集約されると思います。 1.ビジネスロジックでトランザクション管理して、DAOへ引数としてトランザクションを渡す。  当然、コミット・ロールバックはビジネスロジック側で管理。 2.ビジネスロジック側では管理せず、DAO側で管理。  ビジネスロジックへは結果のみ返却。 実は今回のプロジェクト、Java初心者(プログラムって何?レベルとC++なら受講したことあるよ!レベル)が9割を占めるチームです。 初心者の方々はビジネスロジックを設計・実装します。 それ以外の部分(DB・SpringFramework等)を私が設計・実装します。 ビジネスロジックの部分の設計も、概要設計レベルしか記述されておらず、トランザクション無視の設計しかありません。 バグにまみれてデスマーチなんてごめんなので、2のパターンでトランザクションからDB周りを設計したいと思っているのですが、リーダー(スキルは不明。経験はあるらしい)が「DAO側でやると上手くいかない場合が多い」と言われ、却下されそうです。 何処がどう上手くいかないのか聞いても、明確に返答は貰えません。 でもなんとか2のパターンでいきたいのですが、上手い説得方法が見つかりません。 なんて言えば納得してくれそうか、皆様のお知恵を拝借したく投稿しました。 足らない部分は補足させていただきます。 よろしくお願いします。

  • Java
  • 回答数4
  • ありがとう数3

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

RDBですか。通常のRDB利用のシステムは、ビジネスロジック:テーブル=1:nの前提で書きます。 (Aテーブル、Bテーブルからデータを取得し、さらにUIからのパラメータも含め計算し、Cテーブルに格納する等) ですので、私はトランザクションはあくまでビジネスロジックの単位にして、DAOはDBとビジネスロジックの仲介役ぐらいに留めておいた方が無難な気がします。 仮にDAO側でトランザクションを管理するためには、DAO自体の粒度が1トランザクションとなるため、 発生しうるトランザクションを全て考慮しないと整合性のとれたI/Fを持ったDAOが設計できないって事ですよね? 概要設計が出来た箇所から実装しなければいけない今回のPJではことさら難易度が高いのでは? 出来ている部分からDAOを作って、後続の要求に対応するために、ぐちゃぐちゃのI/Fあるいは膨大の数になってしまったDAOの面倒をみなければいけない、なんて辛すぎます。 なので、私は1.の方がいいです。 ビジネスロジックが呼ばれた時点がトランザクションの開始、ビジネスロジックが終了する時点がトランザクションの終わり、 といった形のトランザクションのフレームワークを作って、commit、rollbackを受け持っちゃた方がすっきりしませんか? 長々と書いてしまいましたが、そもそも私のイメージしているシステムと違ったら私の意見は無視してください。相当困難なPJと見受けられますが成功をお祈りしています。

A_Bone
質問者

お礼

ご回答ありがとうございます。 今回DAO側ではSelectに関してはQueryItratorパターン、それ以外に関してはPersisterパターンを参考に実装する予定です。 コネクションはコネクションプーリングを実装する予定です。 Persisterについては複数テーブルに複数操作(Insert/Update/Delete/複数ワザ(Insertで一意制約違反ならUpdateとか))する場合、その途中でExceptionが発生した場合、全てをロールバックする必要もあると考え、単純にPersisterパターンを実装するのではなく、executeUpdateを実行する前にValueObjectと操作内容のMapが(ビジネスロジック側で)設定されたArrayListを解析しながら実行しようと考えています。 つまり1ArrayList1トランザクションといったイメージです。 そうするとビジネスロジック側はDAOのArrayListに値を設定し、最後に全部の操作を一括して行うメソッドを呼び出すだけで、トランザクションのことを気にせずに実装できます。(2のパターンを利用した場合) しかし1のパターンで行った場合、ビジネスロジック側で途中でロールバックをかけるとか、そういうことが果たして(トランザクション/try~catchを知らない初心者に)できるのか?と思わざるを得ません。 Selectに関しては、for updateの時以外は1Select1トランザクションと考えています。 具体的なメソッドとしては検索キーだけを引数に渡すquery(key:Map):Listとトランザクションも引数にしているquery(key:Map, tran:Transaction):Listのパターンを実装予定です。(リーダーは後者のみで良いという事で、トランザクションの管理意識の違いが浮き上がってきた状況です。) > 相当困難なPJと見受けられますが成功をお祈りしています。 ありがとうございます。外注はあくまでも害虫?って状況なので、適当に逃げる手段を作っておかなきゃいけないかもしれませんね。 ともかく、ナントカがんばりたいと思います。

A_Bone
質問者

補足

ここまで書いていて思ったのですが、いっそのことDAOにトランザクションを設定させるsetTransaction(tran:Transaction):voidを作り、実行メソッド呼ばれた時に、クラス変数になけりゃトランザクション作る形ではどうかなと思い始めてますが、プロの目から見ていかがでしょう? 結果として自由度を上げる形になり保守が面倒くさくなると思いますが、初心者の方々が結局どっちを使うかは、コレで明白になると思います。(多分setTransactionは使われないでしょう。トランザクションって何?って言う人達だし。) ビジネスロジックでトランザクション作っても、別でトランザクション作るので、なんだかおかしい感じにはなると思うものの、何よりここでバグが出なくなると思うのですが…ダメですかね?やっぱり^^;

その他の回答 (3)

回答No.3

参考URLの内容によると、DAO[Data Access Object]パターンを使わない場合(質問者さんの言う1.の方)、「データアクセスの手段や実装が変わると、ビジネスロジック中からデータアクセスをしている個所を見つけだし、変更していかなければなりません。」とあります。 個人的には、パターンさえ使えばいい、という考えには少し疑問がありますが、分析・設計の部分がしっかりしていさえすれば、開発者さん達もちゃんと後からついてくるとは思いますが…。

参考URL:
http://www.nulab.co.jp/designPatterns/designPatterns3/designPatterns3-4.html
A_Bone
質問者

お礼

参照URLありがとうございます。拝見いたしました。 なるほど、保守性が下がることを説得材料のひとつとしていけばいいかもしれない ということですね。 納品したら保守なんてやらん って言っているんですが^^; ビジネスロジックは、#1様の補足にも記述させていただきましたが、私は殆どノータッチになります。 リーダーがどうしても1のパターンでやると推し進めるのであれば、デスマーチに入る前にプロジェクト離脱も考えていたりいなかったり^^; あとは、ビジネスロジックの基底クラスを設けて、そこでトランザクション管理をして、それを継承する形でビジネスコンクリートクラス というスタイルも考えていますが、そこまでするんなら、DAOでやっても一緒やん なんて思ってしまいます。 > 分析・設計の部分がしっかりしていさえすれば、開発者さん達もちゃんと後からついてくるとは思いますが…。 そうなんですよね。 でも、そこの部分を書いている人達が「try~catch?」「トランザクション?コミット?何それ?」って言う状態じゃ… ん~~~何でこんなに頑ななんだろう? やっぱり外注の言う事なんて聞きたくない って事なんでしょうか?(涙 ご回答ありがとうございました。

回答No.2

DBはRDB?OODB?XMLDB?どれで考えられてますか?

A_Bone
質問者

補足

DBはRDB、Oracle10gR2を使用予定です。 アドバイスよろしくお願いします。

noname#30871
noname#30871
回答No.1

 あなたは、1のパターンの何処がどう上手くいかないとお考えですか。なぜ、1だとバグにまみれてデスマーチになるのですか。

A_Bone
質問者

補足

補足要求ありがとうございます。 まず、質問にも書きましたが、ビジネスロジックを記述している内容にはトランザクションに関するところが見受けられません。 記述している人に「トランザクション関連はどのように処理される予定ですか?」と聞いたところ「トランザクションって何ですか?」と… 他の人にも聞いてみたのですが、異口同音に「トランザクションって何ですか?コミットって?」という返答でした。 一人、COBOLをやっていた人がいて、その人はコミット・ロールバックが理解できていたようですが、実装するのにどのように取り込めばいいのかも分からない状況のようです。 この状態でまともにビジネスロジックでトランザクション管理が出来るとは思えず、そのまま実装した場合、その箇所でバグが出ることは容易に想像が付きました。 勿論、Java経験2~3年ぐらいのメンバーであれば、当然1のパターンのほうがDB周りを作る負荷は減るので大歓迎なのですが、今回はトランザクション分からない人達にトランザクションについて書けというのは、酷なのではないかと思っています。 そのため、1の方法ではなく2の方法が良いと考えたのです。 また、ビジネスロジックの部分も概要設計レベルの内容で実装するということで、正直、トランザクション管理に関してまで意識がまわらないのではないかとも思ってます。(try~catch も知らない人達なので…) 開発手法も、テストファーストは却下され、とりあえず概要設計が出来上がったところから作って行き、最終的にその中から無作為に数本取り出してテストをするということです。 なので、設計の時点で極力バグが出そうなところを排除しないと、納品間際に受け入れテスト(ここは客が全箇所テスト)でバグにまみれてデスマーチになるんじゃないかと危惧しています。 また、ビジネスロジックの設計書はおよそ60本になり、それらに全てトランザクション管理の記述を入れるのは工数的にも時間がないのが正直なところです。 補足になってないかもしれませんが、アドバイスよろしくお願いします。

関連するQ&A

  • DAOの作成単位について

    MVCでWebアプリを作成していると、ほぼ必ずDAOを作成することになると思いますが、DAOの作成単位にいつも悩みます。今までの経験によると大きく二つ「テーブル単位」か「サービス(ビジネスロジック)単位」にDAOを作成している方が多いようですが、それぞれの作成単位によってメリットデメリットがあると思います。この二つ以外にもDAOの作成単位があるかもしれませんが、どちらがよいのか皆さんの意見を聞かせていただきたいです。 1.テーブル単位 【メリット】  ・同じ処理(SQL)が複数DAOに分散しない 【デメリット】  ・複数テーブル情報をまとめてSELECTするような場合、どのテーブルDAOに実装するか迷う。  ・トランザクション処理が必要な一連の処理を記述する場合、テーブル単位では記述できない。 2.サービス(ビジネスロジック)単位 【メリット】  ・トランザクション処理が必要な一連の処理を記述する場合、違和感が無い。 【デメリット】  ・複数のサービスDAOで同じ処理(SQL)が書かれる可能性がある。

  • .NET Frameworkでサーバ側の処理

    最近、マイクロソフトの.NET Frameworkを利用した、 リッチクライアントの実現(スマートクライアント) についてよく耳にするのですが、いまいちイメージがつかめないので質問させていただきます。 サーバ側にはビジネスロジックのみを実装し、 クライアント側ではユーザーインターフェイスのロジックのみを実装させることで、更新処理を効率化できるとあるのですが、 ・サーバ側で実装するビジネスロジックは、.NETの言語の で記述できるのですか? ・またクライアントから、どのようにしてサーバー側の  ロジックを呼び出すのでしょうか? 全くの初心者質問であるのですが、 なにか情報をお持ちでしたら ぜひ教えていただければと思います。 よろしくお願い致します。

  • ビジネスロジック層とDAO層の書き方

    現在、Webアプリを作成しているのですがビジネスロジックとDAOをどういうように 書けばいいのか困っています。 例えばAテーブルから取得した値を BテーブルとCテーブルにインサート(途中でしくじったらロールバック)。 現在、ビジネスロジック層では下記のような調子で書いています。 しかし、ビジネスロジック層でDAOを直接newするのは依存性の観点から よろしくないということなのですがどのように改善すればよろしいでしょうか。 また、皆様はどのような実装を行っていますでしょうか。 try { DBConnect conn = getConnection(); A aDao = new A(conn); String a = aDao.getData(); B bDao = new B(conn); bDao.insert(a); C cDao = new C(conn); cDao.insert(a); conn.commit(); } catch(Exception e) { conn.rollback(); } finally { conn.close(); } Webを見ていたらDAOパターンを示した下記サイトがありました。 http://www.nulab.co.jp/designPatterns/designPatterns3/designPatterns3-4.html 上記サイトののコードに習うならば上記のビジネスロジックのコードは 下記のようになると思います。(各々のDAOの中でDBのConnection、Closeを行っている) 下記の場合、ビジネスロジックとDAOは疎結合になったかもしれませんが cDao.insert()でしくじった場合、それより前の処理はロールバックできない のではないかと思います。 また、一番最初に書いた記述方法の方が1つのコネクションを各々のDAOで使い回し 最後に正常終了した段階でコミットするというわかりやすさがあるので 一番最初に挙げたコードを改良できないかと思っています。 ItemDao aDao = DaoFactory.createADao(); //Aオブジェクト取得 String a = aDao.getData(); ItemDao bDao = DaoFactory.createBDao(); //Bオブジェクト取得 bDao.insert(a); ItemDao cDao = DaoFactory.createCDao(); //Cオブジェクト取得 cDao.insert(a);

    • ベストアンサー
    • Java
  • 分散トランザクションを開始できなかった

    [OSのVER]:2003server 同士 [SQLServerのVER]:SQLServer2000 StandardEdition SP3 はじめまして! 前のログ(http://www7.big.or.jp/~pinball/discus/sqls/26278.html)で でていたエラーメッセージ サーバー : メッセージ 7391、レベル 16、状態 1、プロシージャ [Microsoft][ODBC SQL Server Driver][SQL Server]OLE DB プロバイダ 'SQLOLEDB' は分散トランザクションを開始できなかったので、要求した操作は実行されませんでした。 [OLE/DB provider returned message: 指定されたトランザクション コーディネータに、新規トランザクションを参加できませんでした。] OLE DB エラー トレース [OLE/DB Provider 'SQLOLEDB' ITransactionJoin::JoinTransaction returned 0x8004d00a]。 と表示されます ビューや、MSDTC(http://support.microsoft.com/?scid=kb;ja;329332&spid=2852&sid=global) などすべてやってみましたがだめでした Enterprise Managerでリンクサーバーを設定して中身を確認する事もできました ビューでその別サーバーのDBを覗くこともできます ストアドでカーソルを使用しています DECLARE M_USER_CSR CURSOR FOR SELECT INPDATE FROM [別サーバ名].DB.dbo.xxxxxx WHERE INPDATE = @COMP_DATE -- システム更新日付比較 と、定義して FETCH NEXT FROM M_USER_CSR としたところで、エラーが表示されます 最初のフェッチではエラーがでず(一件目は正常に内容を取得してます) 二件目のフェッチでエラーがでます どのような解決方法がございますか? どうか教えてください よろしくお願いします ps:サーバー同士はドメイン管理されていません    ワークグループ管理のもと互いに信頼関係は結んでおります

  • 同一レコード更新時の排他制御

    Oracle9iです。 C/S開発で、VB.NETで画面を開発します。 DBの更新は、画面よりストアドプロシージャを使って行います。 複数ユーザが同一レコードを同時に参照し、同一レコードに対して更新された場合、参照時の更新日時と異なる場合はエラーとするよう設計されています。(つまり、後更新はエラー) この排他チェックロジックを画面側で実装しようとしておりますが、この排他チェックロジックを画面側で実装せずに、Oracleよりエラーレコードを受け取ることによる排他制御を行うことはできないでしょうか? ご教授のほどよろしくお願いいたします。 また、参考サイトあれば、その紹介だけでも助かります。

  • ビジネスロジックの実装

    JavaとOracleを使って業務システムを開発しています。 ビジネスロジックをどこに持ってくるか悩んでいます。 ストアドプロシージャにビジネスロジックを実装した方がパフォーマンスもよくなると思うのですが、社内的には反対意見も多いです。 ストアドプロシージャにビジネスロジックことがある方、検討したことがある方、利点や弊害など教えてください。 逆にJava側に乗せた方がよいという方も、ご意見頂戴できればありがたいです。 よろしくお願いいたします。

  • SpringのHibernate連携での条件指定delete

    お世話になります。 spring-framework-1.2.8 hibernate-3.1 でwebアプリの開発を行っております。 宣言的トランザクション管理でDAO作成するために、 HibernateTemplate(org.springframework.orm.hibernate3.support.HibernateDaoSupport#getHibernateTemplate()で取得しています) の各種メソッドでDBアクセスしていますが、条件付delete発行の方法がわかりません。 find()にはクエリ文字列を渡して検索するメソッドがあるのですが、delete()やupdate()にはクエリ文字列を受け取るメソッドがないようです。 HibernateTemplateを使用して条件付delete(SQLのdelete form xxx where xx=x の発行)やupdateは出来ないのでしょうか。 また、条件付deleteはどのように実現すればよいのでしょうか。 よろしくお願いします。

    • ベストアンサー
    • Java
  • C#.NET2005 DllへのWebコントロール渡しについて

    初めまして、towatowatoです。 C#.NET2005(ASP.NET)の開発を行っています。 構成としては下記のようにして開発しています。 ----------------------------------------------- <ソリューション>   --[Webプロジェクト]     |     --Web画面   --[クラスライブラリプロジェクト]     |     --Web画面用ビジネスロジック     |     --Web画面用データロジック ----------------------------------------------- Webプロジェクト側でクラスライブラリプロジェクトで 作成されたDLL参照をして、呼び出ししています。 しかし画面コントロールをビジネスロジックに渡そうにも 下記エラーが表示されます。 ------------------------------------------------------------- 'System.Web.UI.WebControls.WebControl' が参照されていないアセンブリで定義されています。 アセンブリ 'System.Web, ersion=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' への参照を追加してください。 ------------------------------------------------------------- ビジネスロジッククラス側で ”using System.Web.UI”としても認識致しません。 どのようにすればいいのでしょうか? 初歩的な質問かもしれませんが、 何卒ご教授のほどよろしくお願いします。

  • Spring2.0での連続したトランザクションについて

    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> -------------------------------------------------------------- 以上、お手数ですがご指摘お願い致します。

  • セッション管理は必要なのでしょうか?

    iアプリとDBサーバを利用した情報管理システムを考えています。DBはPostgreSQLの予定です。 サーバ側のプログラムはPerlを使って作るつもりです。 iアプリはHTTP通信を行うので、Apacheを立ててCGIでデータベース連携しようと思うのですが、セッション管理ということをしないといけないのか、しなくても良いのかというのが良く分かりません。 具体的には、一日の作業日報をアプリからサーバに送信したり、DB上のデータをダウンロードしたりするくらいのシステムです。 セッション管理は、どのような場合にどのような方法で行うべきものなのでしょうか? またどのような意味があるのでしょうか? かなり初心者レベルのあいまいな質問ですが、アドバイスいただけると助かります。 どうぞよろしくお願いいたします。

    • ベストアンサー
    • Perl