MB blog

こちらは主に自分用のメモです。

ROWNUMで結果のレコード数を制限する

あるカラムでソートした結果の、上位n件だけを抽出したい・・・というときに便利な
LIMIT句というものがあります。

select * from EMPLOYEES
order by EMPLOYEE_ID asc
limit 10;

これで、EMPLOYEE_IDのトップ10件のみ取得できます。
しかし、悲しいことにOracleではLIMIT句がサポートされていない・・・

代替として ROWNUM擬似列なるものを使って取得する必要があります。
ROWNUMとは、ある結果のセットに、仮想的なレコード番号を振ったものです。
このROWNUMを条件句にセットし、結果を制限します。

上記SQLと同様のことがしたい時は、以下のような感じになります。

select * from 
  ( select rownum rn, s.* from 
    ( select * from EMPLOYEES
      order by EMPLOYEE_ID
    ) s
  ) a
where a.rn <= 10 
order by a.rn;

注意点として、rownumは、直接where句やorder by句に指定できないので、
わざわざ入れ子にして別名をつける必要あり。ジャマくさいわね。

JadClipseのインストール on Galileo

とあるライブラリの中身を解読する必要が出てきたので、Eclipse上でデコンパイラJadが使えるようにするプラグイン、JadClipseを入れました。Eclipseは3.5です。

  • jadのインストール

本家のサイトは消えてしまっているので、下記urlのInternetArchiveからダウンロードして、適当なディレクトリに解凍します。
http://web.archive.org/web/20080214075546/http://www.kpdus.com/jad.html#download
WindowsXPはNT系なので、Jad 1.5.8g for Windows 9x/NT/2000 on Intel platform のjadnt158.zipでおkです。

Eclipseの Help > Install New Softwares から、下記のアップデートサイトのurlを入力し、そのままインストールをすすめます。(ちなみに中身は3.3版といっしょ。現在は3.6版まで準備されています)
http://webobjects.mdimension.com/jadclipse/3.5/
インストール完了すると、Eclipseの再起動をすすめられるので、言われるままに再起動します。

  • JadClipseにjad.exeのパスを設定

再起動後、Window > Preference > Java > Jadclipse から、Path to decomplier に、先程解凍したjad.exeのパスを指定します。この手順は、環境変数PATHにjad.exeの場所が通っている場合は不要です。

Eclipseからjar中のclassファイルを開くと、勝手にデコンされたjadファイルが表示されちゃいます。便利!

JPA2.0のLockModeTypeについて

JPA2.0における変更点

Java EE 6仕様の一部であるJPA2.0。
JPA1.0からの変更点のひとつに、エンティティ更新時のリソースロック機能として悲観ロックをサポートするようになった、というものがあります。EntityManager # find や lock といったメソッドの引数に指定できるデータベースのロックタイプ(javax.persistence.LockModeType)が、1.0までは

  • READ
  • WRITE

の2種類だったのが、

  • OPTIMISTIC
  • OPTIMISTIC_FORCE_INCREMENT
  • PESSIMISTIC_READ
  • PESSIMISTIC_WRITE
  • PESSIMISTIC_FORCE_INCREMENT

の5種類が追加されたようです。

また、Query # setLockMode というメソッドも新たに追加され、ユーザが定義したJPQLクエリ時代に、ロックタイプ属性を持たせられるようになっています。さて、新たに追加された5種類のLockModeTypeについて、Javadocを見ただけでは動きが分からなかったので、調べてみました。

楽観ロック

既存のREADとWRITEに対応するもののようです。READ, WRITEは今後、deprecatedになっていくのでしょうか?バージョン番号/最終更新時間による更新チェックをかけるので、バージョン更新に対応したエンティティオブジェクトにのみ対応している、という点も同様です。
ここでいう"バージョン更新に対応したエンティティオブジェクト"とは、以下の条件を満たすもののことです。

  • 対象となるテーブルに、バージョン番号 or 最終更新時間をあらわすカラムがある
  • 上記カラムに対応するフィールドを、エンティティBeanが持っている
  • 上記フィールドのセッターに @Version アノテーションが付与されている

JPA2.0で指定できる楽観ロックは、以下2タイプです。

OPTIMISTIC
  • エンティティ更新のコミット時にのみ、対象データをロックし、バージョン更新がかかる
OPTIMISTIC_FORCE_INCREMENT
  • エンティティ更新のコミット時だけでなく、ただエンティティを参照しただけでデータに変更を加えていない場合も、強制的にバージョン更新がかかる

悲観ロック

DBに長時間の排他ロックをかける悲観ロックは、1.0まではJPAの標準仕様ではサポートされていませんでした(各プロバイダの実装により、ヒント句を利用して悲観ロックをかける方法は存在しました)。なお悲観ロックにおいては、楽観ロックのように、バージョン更新に対応したエンティティオブジェクトを用意する必要はありませんが、もしバージョ更ン更新に対応したエンティティオブジェクトに悲観ロックをかけた場合は、楽観ロックと同じ方法でバージョンチェックおよび更新が行われます。JPA2.0で使用できる悲観ロックは、以下3タイプです。

PESSIMISTIC_READ
  • エンティティを取得した時点から、対象データにロックがかかる
  • コミット時にロック解放される
PESSIMISTIC_WRITE
  • エンティティを更新した時点から、対象データにロックがかかる
  • エンティティを取得・参照するだけだと、
  • 取得時から更新時までのあいだに他トランザクションに介入されたとき、更新失敗やデッドロック誘発のおそれがある
  • コミット時にロック解放される
PESSIMISTIC_FORCE_UPDATE
  • バージョン更新に対応したエンティティオブジェクトにしかかけられない
  • エンティティを取得した時点から、対象データにロックがかかる
  • エンティティを参照しただけで変更を加えていない場合も、強制的にバージョン更新がかかる
  • コミット時にロック解放される

〜参考〜
JSR-000317 JavaTM Persistence 2.0(Final Release)
Locking and Concurrency in Java Persistence 2.0

JPAのトランザクションについて

JPAトランザクションについてまとめました。

  • エンティティマネージャの種類
    • コンテナ管理
      • EJBコンテナがライフサイクルを管理
      • DI or JNDI lookupにより取得
    • アプリケーション管理
      • アプリケーションのコード上で生成・破棄
      • EntityManagerFacutory # createEntityManager() により生成
      • EntityManager # close() で破棄
エンティティマネージャのタイプ トランザクションのタイプ 環境
コンテナ管理 JTA EJBコンテナ
アプリケーション管理 JTA EJBコンテナ, Webコンテナ
アプリケーション リソースローカル EJBコンテナ, Webコンテナ, Java SE

Apacheを非rootユーザで起動する

httpd.confに指定したapacheユーザ(非root)で、Apacheのリスンポートを81番で起動しようとしたところ、以下のエラー。

(13)Permission denied: make_sock: could not bind to address 0.0.0.0:81

1023番以下の特権ポートはrootユーザ以外はリスンさせられないということなので、httpd.confを編集し、リスンポートを7777に変更。
再度起動しようとすると、以下のエラー。

(13)Permissin denied: httpd: could not open error log file //logs/error_log.
Unable to open logs

logs以下のオーナーがrootになっているため、ログファイルが開けず、起動できないようです。
chown -R hoge:hoge logs してリトライすると、無事動かせました。

ARCHIVELOG/NOARCHIVELOG 確認方法

以下のコマンドで、確認できます。

SQL> archive log list

Database log mode Archive Mode
Automatic archival Enabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 19
Next log sequence to archive 21
Current log sequence 21

または、V$DATABASEビューのLOG_MODE列。

SQL> select LOG_MODE from V$DATABASE

ARCHIVELOG/NOARCHIVELOGの切り替えは、オンラインREDOログが読み込まれているmount状態で、

SQL> alter database archivelog(/noarchivelog);
SQL> archive log start
Statement processed.
SQL> alter database open;

sql*plusの設定を起動時に自動的に読み込ませる

以下ファイルに設定を記録します。
$ORACLE_HOME/sqlplus/admin/glogin.sql

設定例。

set lines 300 pages 5000 timing on

set sqlp "SQL &_user> "

<&_user>には、ログイン中のスキーマ名が表示されます。

set autocommit off

11gR2から、なぜかautocommitがデフォルトでonになっているので、自動コミットオフにしておくのは重要です。

快適なSQL*Plus生活が送れそうですね。