S2DAOで気になること

トランザクション分離性はどうやって設定するのか?

  • S2DAOでは出来ない。アプリケーションサーバとかで設定する。

大量のレコードを読み取りつつメモリは節約したい時どうするか?

概念的には

  • 普通にJDBCでやる場合は、Statement#setFetchSize()を指定しなければ全件がクライアントにキャッシュされる。適切な値を指定すれば、その数だけキャッシュされ、キャッシュ範囲をnext()で超える場合、次の分が読み取られ、キャッシュされる。
  • S2JDBCでは、StatementのFetchSizeを指定出来る。しかし、いずれにせよJavaオブジェクトとなって全件がメモリ上に展開されることになる。
  • S2DAOでは、StatementのFetchSizeは指定出来そうにない。DAOでgetAll()を作れば、全件分のJavaオブジェクトがメモリ上に展開される。
  • その全件というのが膨大であった場合、メモリ上に全件を展開することは出来ないだろう。その場合どうするか?
  • 1つのアイディアとしては、キーだけは全件をメモリ上に展開し、キー以外を含めた全項目は1レコード毎にメモリ上に展開するようにする。この方法なら、S2DAOを上手く使えば(DAOメソッドの組み合わせで)出来る。
  • キーだけでも全件をメモリ上に展開したくないのであれば、キーだけを取得するResultSetを持って回して行くしかない?もちろんFetchSizeを設定しておかなければ本末転倒であろうが。
  • この方法では、それなりの時間、ResultSetが保持されるだろう。これがDB2とかだったら共有ロックがかかるので、更新処理の実行が待たされ、同時実行性が極端に落ちるだろう。OracleならFOR UPDATEを付けない限りロックはかからず、REDO領域を使ったマルチバージョン読み取り一貫性があるので、問題ないだろう。あくまで1つのSQLによる1つのResultSetなので、このケースではREAD COMMITEDとSERIALIZEDで動きに違いはないはず?

booleanをY/Nで持つ

  • StatementFactory、PreparedStatement、CallableStatementを継承したクラスで対応する。
  • ResultSetも要対応。ResultSetFactory、ResultSetを継承したクラスで対応する。但し、Y/Nをbooleanにするために、BooleanConversionUtilの修正が必要となる。

YYYYMMDDをDateか何かで持つ

  • 修正は上記booleanと同じ(BooleanConversionUtil以外)。結局、YYYYMMDDの時だけ、他の日時系メソッドと違うメソッドを使わないとうまく制御出来ないのだが、デフォルトのS2DAOではjava.sql.Dateがそれにあたる。ValueTypesでregistしているので、そこ次第。

この記事を書いた人

井上 研一

株式会社ビビンコ代表取締役、ITエンジニア/経済産業省推進資格ITコーディネータ。AI・IoTに強いITコーディネータとして活動。画像認識モデルを活用したアプリや、生成AIを業務に組み込むためのサービス「Gen2Go」の開発などを行っている。近著に「使ってわかった AWSのAI」、「ワトソンで体感する人工知能」。日本全国でセミナー・研修講師としての登壇も多数。