Java Persistence API で遊ぶ - 2 -

ゆっちの秘密基地
Master - Yucchi
Since - 2012/05/05


Java秘密基地

Java Persistence API で遊ぶ - 2 -
Java Persistence API で遊ぶ -1-の続きです。

今回は NetBeans6.0RC1 によって自動生成されるエンティティクラスについて調べてみます。

開発環境は

OS   Windows Vista Ultimate 64bit
JDK6u3
NetBeans IDE 6.0 RC1
MySQL 5.0.45 (Community 版)

です。

利用するデータベースはこのような構造です。







各テーブルは下記のようになってます。

talent テーブル

DROP TABLE IF EXISTS `talentdb`.`talent`;
CREATE TABLE  `talentdb`.`talent` (
  `TALENT_ID` int(10) unsigned NOT NULL auto_increment,
  `TALENT_NAME` varchar(45) NOT NULL,
  `OFFICE_ID` int(10) unsigned default NULL,
  `ADDRESS_ID` int(10) unsigned default NULL,
  `HOBBY_ID` int(10) unsigned NOT NULL,
  `HEIGHT` int(10) unsigned default NULL,
  `BUST` int(10) unsigned default NULL,
  `WAIST` int(10) unsigned default NULL,
  `HIPS` int(10) unsigned default NULL,
  `BIRTHDAY` date default NULL,
  PRIMARY KEY  (`TALENT_ID`),
  KEY `FK_talent_1` (`OFFICE_ID`),
  KEY `FK_talent_2` (`ADDRESS_ID`),
  KEY `FK_talent_3` (`HOBBY_ID`),
  CONSTRAINT `FK_talent_1` FOREIGN KEY (`OFFICE_ID`) REFERENCES `office` (`OFFICE_ID`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_talent_2` FOREIGN KEY (`ADDRESS_ID`) REFERENCES `address` (`ADDRESS_ID`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_talent_3` FOREIGN KEY (`HOBBY_ID`) REFERENCES `hobby` (`HOBBY_ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=sjis;
	

office テーブル

DROP TABLE IF EXISTS `talentdb`.`office`;
CREATE TABLE  `talentdb`.`office` (
  `OFFICE_ID` int(10) unsigned NOT NULL auto_increment,
  `OFFICE_NAME` varchar(100) NOT NULL,
  `ADDRESS` varchar(100) NOT NULL,
  PRIMARY KEY  (`OFFICE_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=sjis;


hobby テーブル

DROP TABLE IF EXISTS `talentdb`.`hobby`;
CREATE TABLE  `talentdb`.`hobby` (
  `HOBBY_ID` int(10) unsigned NOT NULL auto_increment,
  `HOBBY_NAME_1` varchar(45) default NULL,
  `HOBBY_NAME_2` varchar(45) default NULL,
  `HOBBY_NAME_3` varchar(45) default NULL,
  PRIMARY KEY  (`HOBBY_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=sjis;


project テーブル

DROP TABLE IF EXISTS `talentdb`.`project`;
CREATE TABLE  `talentdb`.`project` (
  `PROJECT_ID` int(10) unsigned NOT NULL auto_increment,
  `PROJECT_NAME` varchar(100) default NULL,
  `PLATFORM` varchar(100) default NULL,
  PRIMARY KEY  (`PROJECT_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=sjis;


talent_project テーブル

DROP TABLE IF EXISTS `talentdb`.`talent_project`;
CREATE TABLE  `talentdb`.`talent_project` (
  `TALENT_ID` int(10) unsigned NOT NULL,
  `PROJECT_ID` int(10) unsigned NOT NULL,
  PRIMARY KEY  (`TALENT_ID`,`PROJECT_ID`),
  KEY `FK_TALENT_PROJECT_2` (`PROJECT_ID`),
  CONSTRAINT `FK_TALENT_PROJECT_1` FOREIGN KEY (`TALENT_ID`) REFERENCES `talent` (`TALENT_ID`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_TALENT_PROJECT_2` FOREIGN KEY (`PROJECT_ID`) REFERENCES `project` (`PROJECT_ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=sjis;


genre テーブル

DROP TABLE IF EXISTS `talentdb`.`genre`;
CREATE TABLE  `talentdb`.`genre` (
  `GENRE_ID` int(10) unsigned NOT NULL auto_increment,
  `GENRE_NAME_1` varchar(100) NOT NULL,
  `GENRE_NAME_2` varchar(100) default NULL,
  `GENRE_NAME_3` varchar(100) default NULL,
  PRIMARY KEY  (`GENRE_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=sjis;


talent_genre テーブル

DROP TABLE IF EXISTS `talentdb`.`talent_genre`;
CREATE TABLE  `talentdb`.`talent_genre` (
  `TALENT_ID` int(10) unsigned NOT NULL auto_increment,
  `GENRE_ID` int(10) unsigned NOT NULL,
  PRIMARY KEY  (`TALENT_ID`,`GENRE_ID`),
  KEY `FK_TALENT_GENRE_1` (`GENRE_ID`),
  CONSTRAINT `FK_TALENT_GENRE_1` FOREIGN KEY (`GENRE_ID`) REFERENCES `genre` (`GENRE_ID`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_TALENT_GENRE_2` FOREIGN KEY (`TALENT_ID`) REFERENCES `talent` (`TALENT_ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=sjis;


email テーブル

DROP TABLE IF EXISTS `talentdb`.`email`;
CREATE TABLE  `talentdb`.`email` (
  `EMAIL_ID` int(10) unsigned NOT NULL auto_increment,
  `HOLDER_ID` int(10) unsigned default NULL,
  `EMAIL_ADDRESS` varchar(100) NOT NULL,
  PRIMARY KEY  (`EMAIL_ID`),
  KEY `FK_email_1` (`HOLDER_ID`),
  CONSTRAINT `FK_email_1` FOREIGN KEY (`HOLDER_ID`) REFERENCES `talent_email` (`HOLDER_ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=sjis;


talent_email テーブル

DROP TABLE IF EXISTS `talentdb`.`talent_email`;
CREATE TABLE  `talentdb`.`talent_email` (
  `HOLDER_ID` int(10) unsigned NOT NULL,
  `EMAIL_ID` int(10) unsigned NOT NULL,
  PRIMARY KEY  (`HOLDER_ID`,`EMAIL_ID`),
  KEY `FK_TALENT_EMAIL_1` (`EMAIL_ID`),
  CONSTRAINT `FK_TALENT_EMAIL_1` FOREIGN KEY (`EMAIL_ID`) REFERENCES `email` (`EMAIL_ID`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_TALENT_EMAIL_2` FOREIGN KEY (`HOLDER_ID`) REFERENCES `talent` (`TALENT_ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=sjis;


address テーブル

DROP TABLE IF EXISTS `talentdb`.`address`;
CREATE TABLE  `talentdb`.`address` (
  `ADDRESS_ID` int(10) unsigned NOT NULL auto_increment,
  `PREFECTURE` varchar(45) default NULL,
  `CITY` varchar(45) default NULL,
  PRIMARY KEY  (`ADDRESS_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=sjis;


phone テーブル

DROP TABLE IF EXISTS `talentdb`.`phone`;
CREATE TABLE  `talentdb`.`phone` (
  `HOLDER_ID` int(10) unsigned NOT NULL auto_increment,
  `PHONE_NUMBER` varchar(45) default NULL,
  PRIMARY KEY  (`HOLDER_ID`),
  CONSTRAINT `FK_PHONE_1` FOREIGN KEY (`HOLDER_ID`) REFERENCES `talent` (`TALENT_ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=sjis;


以上のようなテーブルを使用します。


それでは新規プロジェクトをつくりましょう。

[ File ] → [ New Project... ] で新規プロジェクトを作ります。

新規プロジェクトウィンドウが表示されます。

[ Java ] → [ Java Application ] を選択し [ Next > ] ボタンを押します。

次のステップでは下記のようにプロジェクト名、ロケーションなどを設定します。

そして、[ Finish ] ボタンを押します。







データベースからエンティティクラスを作ります。








[ データベース接続 ] を選択し、利用するデータベースに接続します。

利用可能な表から先ほどのテーブルを選択し追加します。

リレーションシップがとられている表は自動的に選択されてしまします。






エンティティクラスの設定をします。

今回は [ 持続フィールド用の NamedQuery 注釈を生成 ] のチェックを外しておきます。

[ 持続性ユニットを生成... ] ボタンを押します。






持続性ユニット名をつけて [ 作成 ] ボタンを押します。






設定を確認して [ 完了 ] ボタンを押します。






下図のようなエンティティクラスが作成されたことが確認できます。





talent テーブルから作成されたエンティティクラスのソースコードの一部です。









それでは talent テーブルから作成されたエンティティクラスと各テーブルから作成されたエンティティクラスの関係を確認してみます。



talent テーブルと office テーブルから生成されたエンティティクラスの確認


Talent.java のソースコードの一部





Office.java のソースコードの一部




Talent.java が主で ManyToOne になっているのが解ります。

Office.java は従で OneToMany です。

ちゃんとリレーションシップがとれてます。



それではよく似た構造の hobby テーブルから作成されたエンティティクラスとの関係を見てみましょう。


Talent.java




Hobby.java




Talent.java が主で ManyToOne になってます。

しかし、Hobby.java は従で OneToMany になってますがカスケード戦略がとられてます。

これは talent テーブルの HOBBY_ID ( 外部キー ) が NOT NULL になっているからです。

このようなことを解析し、エンティティクラスを自動生成する機能は素晴らしいですね。



次は project テーブルから生成されたエンティティクラスを確認します。


Talent.java





Project.java




Talent.java が主で ManyToMany で生成されてます。

もちろん、ジョインテーブルを解析して @JoinTable アノテーションも使われています。

Project.java は従で ManyToMany で生成されてます。

project テーブルの PROJECT_NAME , PLATFORM のデフォルト値が null だからでしょう。



では、同じようなテーブル構造の genre テーブルから生成されたエンティティクラスを確認します。

Talent.java





Genre.java




Talent.java が従で ManyToMany

Genre.java が主で ManyToMany となってます。

同じ双方向 ManyToMany でも主側が genre テーブルになってます。

GENRE_NAME_1 が NOT NULL になっているからでしょう。

次に同じくジョインテーブルを利用したリレーションシップをとっている email テーブルから生成されたエンティティクラスを確認します。


Talent.java




Email.java




Talent.java が従で ManyToMany

Email.java が主で ManyToMany

さきほどの Genre.java と一緒ですね。

本当は単方向 OneToMany を実現するためにジョインテーブルを用意したのだけどNetBeans6.0 はそこまで解るはずがないのでこのようになりました。

つまりジョインテーブルを利用すると双方向 ManyToMany になってしまうようです。





次はaddress テーブルから生成されたエンティティクラスを確認します。

Talent.java




Address.java




Talent.java が主で ManyToOne です。

Address.java が主で OneToManyです。

これは Office.java と一緒ですね。

本当は単方向 OneToOne にする予定だったのですがこのようになってしまいました。

あとで修正すれば問題なさそうです。




次は phone テーブルから生成されるエンティティクラスを確認します。

Talent.java





Phone.java




Talent.java が従で OneToOne です。

カスケード戦略がとられてます。

Phone.java が主で OneToOne です。

読み取り専用属性が指定されてます。

ちゃんとテーブル構造を解析してくれてますね。

素晴らしいです。



データベースのテーブル構造を解析しエンティティクラスを自動生成する機能は素晴らしいものです。

恐るべし! NetBeans6.0 !


    Home  Index  Back Next