プライマリキーの扱い

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のバグなのかも??ちょっと調査してますよー。