Cayenne + Wicket のシリアライゼーション
もやもやしていたのでCayenneのデシリアライズとHollowの状態についてメモ。
http://cayenne.apache.org/doc/persistent-object-lifecycle.html
CayenneDataObject.java
private void writeObject(ObjectOutputStream out) throws IOException { out.writeInt(persistenceState); switch (persistenceState) { // New, modified or transient or deleted - write the whole shebang // The other states (committed, hollow) all need just ObjectId case PersistenceState.TRANSIENT: case PersistenceState.NEW: case PersistenceState.MODIFIED: case PersistenceState.DELETED: out.writeObject(values); break; } out.writeObject(objectId); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { this.persistenceState = in.readInt(); switch (persistenceState) { case PersistenceState.TRANSIENT: case PersistenceState.NEW: case PersistenceState.MODIFIED: case PersistenceState.DELETED: values = (Map<String, Object>) in.readObject(); break; case PersistenceState.COMMITTED: case PersistenceState.HOLLOW: this.persistenceState = PersistenceState.HOLLOW; // props will be populated when required (readProperty called) values = new HashMap<String, Object>(); break; } this.objectId = (ObjectId) in.readObject(); // DataContext will be set *IF* the DataContext it came from is also // deserialized. Setting of DataContext is handled by the DataContext // itself }
状態がCOMMITTEDの場合はvalues(DBのデータに対応)はwriteObjectで保存されない。
Whenever such object is "touched" by the user (i.e. a setter or a getter is invoked), Cayenne automatically infaltes it with the database values.
http://cayenne.apache.org/doc/cayenne-contract.html
ここにはget系メソッドを呼び出せば自動的にselectされると書いてある。
しかし
public Object readProperty(String propertyName) { if (objectContext != null) { // will resolve faults ourselves below as checking class descriptors for the // "lazyFaulting" flag is inefficient. Passing "false" here to suppress fault // processing objectContext.prepareForAccess(this, propertyName, false); } Object object = readPropertyDirectly(propertyName); if (object instanceof Fault) { object = ((Fault) object).resolveFault(this, propertyName); writePropertyDirectly(propertyName, object); } return object; }
objectContextがnullの場合は無視される。objectContextはシリアライズされていないので、単純にPersistentクラスをデシリアライズしただけではデータは復元されない。
上のコメントで
// DataContext will be set *IF* the DataContext it came from is also // deserialized. Setting of DataContext is handled by the DataContext // itself
と書いてある。
これはもしかして…と思ってページクラスに@Injectアノテーションで取得していたObjectContextのオブジェクトを、コンストラクタで手動登録するようにした。
そしたらHollow状態にならなかった!
これは…。Guice と wicket-guiceの動作を調べる必要があるかも。