プライマリキーの扱い
Cayenneのプライマリキーの管理は、基本的に「おまかせ」です。ほかのO/Rマッパーはよく知りませんが、EOFも同様です。
たとえば新しくデータをインサートする時などはプライマリキーの生成もCayenneが行ってくれます。そのための特別なテーブル(AUTO_PK_SUPPORT)が作られる場合もあります。(EOFではAUTO_PK_TABLEでしたっけ?)
CREATE TABLE AUTO_PK_SUPPORT ( TABLE_NAME CHAR(100) NOT NULL, NEXT_ID INTEGER NOT NULL);
例えばEmployeeというテーブルを用意すると
CREATE TABLE Employee (empno INTEGER NOT NULL, ename VARCHAR(16) , sal FLOAT, PRIMARY KEY (empno));
コレに対応するEmployeeクラスは
Employee.java
public class Employee extends DataObject { public void setEname(String ename) {...} public String getEname() {...} public void setSal(Float sal) {...} public Float getSal() {...} }
のような感じになります(ソースは適当です)。つまり、プライマリキーはユーザー側ではいっさい見ません。(empnoのゲッター/セッターがありません)
新しくEmployeeを追加する場合は、AUTO_PK_SUPPORTテーブルに以下のようなSQLが自動的に発行されて、新しいプライマリキーを発行します。
SELECT NEXT_ID FROM AUTO_PK_TABLE WHERE TABLE_NAME = 'Employee';
NEXT_IDをインクリメントして、
UPDATE AUTO_PK_TABLE SET NEXT_ID = NEXT_ID + 20 WHERE TABLE_NAME = 'Employee';
ただし、使用するデータベースによっては、AUTO_PK_TABLEを使用せずに、データベース自身が持つシーケンスなんかをつかう場合もあるようです。詳しくはドキュメントの4.7.3 Generated Primary Keyを参照してください。
もちろん、
public void setEmpno(Integer empno); public Integer getEmpno();
をEmployeeオブジェクトに定義しても構いませんし、問題なく動作します。この場合はAUTO_PK_SUPPORTにUPDATEをかけるような動作はしません。プライマリキー管理はユーザ側で責任持ってねという事になります。
ちなみにプライマリキーを参照するメソッドが定義されていない場合でも、DataObjectUtilクラスでプライマリキーの値を取ってくる事は可能です。(EOFのEOUtilities.primaryKeyForObject()に相当。)
おそらくCayenneの住人(って、日本にいるんだろうか・・・?)、EOF界隈の人たちはプライマリキーについてあまり意識した事無いんじゃないかなあ?(一部から反発食らいそうですが(笑))
もちろん、プライマリキー自体に「意味がある」ってのはかなり多いと思いますんで、その辺の事はドキュメント 4.7.1 Meaningful Primary Key にも言及されています。
で、結局の所、キーの管理はCayenneにお任せでも、自分で管理しても、どちらでも構わないんですが、S2Cayenneでちょっと困った事がありまして・・
このプライマリキーの自動生成ですが、AUTO_PK_SUPPORTにアクセスする際、否応無しにInternalTransactionを使うんですよー。こりゃ参ったなー。Cayenneのバグなのかも??ちょっと調査してますよー。