DBクエストIII〜そして伝説(ORMapping)へ〜中編


あらすじ


 DBのどうくつを こうりゃくするため
ORマッピングの マジックアイテム
ハイバーネイトの スコップを さがしだした
ゆうしゃ じゅいち だったが
そのハイバーネイト スコップは みぎききようだった


ひだりきき(NetBeansつかい)である
ゆうしゃは ふたたび たんさくの たびにでた


さまざまなサイトを たずねると さいきん
Java けんきゅうじょが きょだいくっさくマシン
JBを はつばいした といううわさを ききつけた
それがあれば ハイバーネイトスコップは いらないのだ


JBマシンの ふくざつな そうさほうを
まなぼうと いくつか サイトをめぐっていると
とおりがかりの けんじゃキシダに 「JPAの ドリルなら
JBを つかわなくても らくに DBに はいれる」
とおそわった


ゆうしゃ じゅいちの ぼうけんは つづく・・・



 と、言うわけで、JPAの勉強をする。マイコミジャーナル
http://journal.mycom.co.jp/special/2006/jpa/index.html
が分かりやすく、手間も少なそうだ。データベースが「H2」になるが、気にしない。というかH2はJavaで書かれたデータベースシステムだそうで、むしろJavaプログラムと親和性が良いかもしれない。
 とにかく上記のサイトの(4)〜(6)をそのまま実行してみた。しかし!目標である

2つのPersonオブジェクトを永続化中
2つのPersonオブジェクトを永続化しました.

 にはたどり着けなかった!Mainクラスを実行してもNetBeans

init:
deps-jar:
compile-single:
run-single:
Exception in thread "main"
 java.lang.NullPointerException
    at oracle.toplink.essentials.ejb.cmp3.
     EntityManagerFactoryProvider.
      createEntityManagerFactory
       (EntityManagerFactoryProvider.
        java:120)
    at javax.persistence.Persistence.
      createEntityManagerFactory
       (Persistence.java:83)
    at javax.persistence.Persistence.
       createEntityManagerFactory
        (Persistence.java:60)
    at jpasample.Main.init(Main.java:30)
    at jpasample.Main.main(Main.java:45)
Java Result: 1
構築成功 (合計時間: 1 秒)

と返すだけで、データベースにもなんの変化もないのだ。例外起きてるのに構築成功ってどないやねん!しかもコンパイル成功したなら実行しろよ!ランタイムエラーなら分かるが、それすら表示しないで終了とはどういう了見だッ!?
 だいたいなんだよこのエラーメッセージ!こんな断片的なメッセージで何が分かるッ!俺は名探偵じゃねぇぇぇ!
NullPointerExceptionだと?つまり値が未定義(null=からっぽ)の変数を参照しようとした、という意味だが

29    public void init() {
30        factory = Persistence.createEntityManagerFactory("sample");
31        manager = factory.createEntityManager();
32    }
42    public static void main(String[] args) {
43        // TODO code application logic here
44        Main main = new Main();
45        main.init();
46        try {    
47            main.create();
48        } catch (RuntimeException ex) {
49            ex.printStackTrace();
50        } finally {
51            main.shutdown();
52        }
53    }

 45はinit()を呼び出すからぬるぽはありえないというか30のあおりを食らってるんだろう。でも30でなんでぬるぽが発生するの!?オートコレクトのお陰でPersistenceクラスにはcreateEntityManagerFactory(String)という関数があることは分かっている。だから"sample"という文字列を引数にすることは正しいはずだ。何がおかしいのだ!しかしライブラリはclassファイルしかないからどういう構造なのかサッパリ分からん(怒)!ソースファイルも上記のサイトからコピーアンドペーストしたのになーーーー。
 この"sample"はpersistence.xmlファイルに記されているタグの中身に対応している。他に"sample"はない。つづりはあってる。コピペまでして試した。さらにXMLファイルの方を"samplee"に変えてみても同じ結果だった。ということはこれが原因ではない。
 データベースをpostgreに変更して同様にやってみたがだめだった。(実行時ウインドウで設定したデータベース設定そのままに自動生成してくれるから嬉しい。)それどころか実行時ウインドウでデータベースを切断した状態でも同じ結果だった。ということはこれが原因ではない。


なんでじゃぁーーー!?


 ところでそれはそれとして、上記のサイトに示されたソースがほんとに正しいのか気になる。
他のEJBを紹介したサイトの記述を見るとアノテーション(変数定義の直前に@Column(name = "middle_name")とか記述すること)が色々書き込まれているのだが、こちらにはクラスと、Idという変数にあるだけ。あれ?nameという変数は・・・?しかもデータベースの列名との対応付けはなし。どうやって関連付けしてるんだろう・・・?
 同じEJBなのになんでこんなに簡素なんだろう。これがJPAの威力なのだろうか?ふーむどうやら
http://www.beasys.co.jp/dev2dev/pub/a/2006/03/jpa-spring-medrec.html
の記事によると

JPAでは、永続性とオブジェクト/リレーショナルマッピングに関係するJPAメタデータを外部XMLファイル、Java 5.0注釈、あるいはその両者の組み合わせのどれで指定するかを開発者が選択することができます。

ということらしい。ずいぶんと自由度が高いようだが・・・。しかもアノテーションが少ないのは

クラスの永続フィールドには、注釈が付いていないものがあることに注意してください。これは、JPAで定義されるデフォルト(つまり、デフォルトカラム名)がこれらのフィールドの場合には正しかったためです。フィールド名とそのマッピング先のデータベースカラム名が異なる場合には、Column注釈を使用して、正しいデータベースカラム名を指定する必要があります。

ということらしい。すげえ・・・なんという省力化。