1 対 N の関係を持つ次の永続クラスがあります。
@PersistenceCapable
public class Pet {
@Persistent(primaryKey = "true", valueStrategy = IdGeneratorStrategy.IDENTITY)
Long id;
@Persistent
String name;
@Element(column = "PET_ID")
List<Photo> photos;
// getters and setters
と
@PersistenceCapable
public class Photo {
@Persistent(primaryKey = "true", valueStrategy = IdGeneratorStrategy.IDENTITY)
Long id;
@Persistent
String desc;
@Persistent(serialized="true")
Object image;
// getters and setters
// hash and equal using field id
フィールドリストの写真は、FK を使用して、ペット (1) と写真 (N) の間に 1 対 N の関係を確立します。Photo のField Object 画像は、画像オブジェクトを保持するためにシリアル化されたものです。
データストア操作には、次のメソッドを持つ PetDao を使用します
public final static PersistenceManagerFactory pmf = JDOHelper
.getPersistenceManagerFactory("datastore");
public void storePet(Pet pet) {
// get PM and current tx
try {
tx.begin();
pm.makePersistent(pet);
tx.commit();
} catch (Exception e) {
// rollback and close pm
}
}
public void storePhoto(Long petId, Photo photo) {
// get PM and current tx
try {
tx.begin();
Pet pet = pm.getObjectById(Pet.class,petId);
pet.addPhoto(photo);
tx.commit();
} catch (Exception e) {
// rollback and close pm
}
}
オブジェクトを作成して永続化します
Pet pet = new Pet();
pet.setName("Nicky");
Photo photo = new Photo();
photo.setDesc("Photo 1");
photo.setImage(new Image("image 1"));
pet.addPhoto(photo);
.... add photo 2 and photo 3
PetDao petDao = new PetDao();
petDao.storePet(pet);
// i have one more photo so add it directly
photo = new Photo();
photo.setDesc("Photo 4");
photo.setImage(new Image ("image 4"));
petDao.storePhoto((long)0, photo);
すべてが必要に応じて持続し、データストアの PET テーブルには 1 匹のペットが、PHOTO テーブルには 4 枚の写真が格納されます。
しかし、petDao.storePhoto((long)0, photo)コードの DataNucleus ログを分析すると、DataNucleus がデータストアからすべての画像オブジェクトを取得していることがわかります。
Native [DEBUG] INSERT INTO PHOTO ("DESC",IMAGE,PET_ID,PHOTOS_INTEGER_IDX) VALUES (<'Photo 4'>,<UNPRINTABLE>,<0>,<3>)
Persist [DEBUG] Execution Time = 70 ms (number of rows = 1) on PreparedStatement "org.datanucleus.store.rdbms.ParamLoggingPreparedStatement@190a0d6"
Persist [DEBUG] Object "in.m.pet.Photo@10deb5f" was inserted in the datastore and was given strategy value of "3"
Native [DEBUG] SELECT A0.IMAGE FROM PHOTO A0 WHERE A0.ID = <1>
Retrieve [DEBUG] Execution Time = 1 ms
Native [DEBUG] SELECT A0.IMAGE FROM PHOTO A0 WHERE A0.ID = <0>
Retrieve [DEBUG] Execution Time = 0 ms
Native [DEBUG] SELECT A0.IMAGE FROM PHOTO A0 WHERE A0.ID = <2>
Retrieve [DEBUG] Execution Time = 0 ms
INSERT INTO PHOTO... ステートメントを使用して「写真 4」を追加した後、DataNucleus は 3 つの SELECT IMAGE FROM PHOTO ステートメントを起動して、以前の 3 つの画像オブジェクトを取得します。イメージ オブジェクトの数が増えると、これらの取得は非常に大きくなる可能性があり、その結果、データストアに不要な負荷がかかり、パフォーマンスに影響を与えます。
pm.getObjectById() を使用してペットを選択し、Pet オブジェクトを切り離し、切り離されたオブジェクトに写真を追加してから、pm.makePersistent(pet) を使用してオブジェクト グラフに再び添付すると、同じことが起こります。FetchGroupは次のとおりです
@PersistenceCapable(detachable="true")
@FetchGroup(name="detachPhotos", members={@Persistent(name="photos")})
public class Pet {
....
}
fetchgroup でペットをデタッチします
public Pet getPet(Long id){
PersistenceManager pm = pmf.getPersistenceManager();
pm.getFetchPlan().addGroup("detachPhotos");
Pet pet = pm.getObjectById(Pet.class, id);
return pm.detachCopy(pet);
}
私の質問は、データストアからのオブジェクト イメージのこれらの不必要な再試行を回避する方法です。
別のアプリから petDao.storePhoto((long)0, photo) を呼び出すか、PetDao.storePhoto メソッドで PMF の別のインスタンスを使用すると、DataNucleusはSELECT を起動して画像オブジェクトを取得しません。