我有以下具有 1 对 N 关系的 Persistable 类。
@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
Field List photos使用 FK 在 Pet (1) 和 Photo (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 语句检索前面的三个图像对象。随着图像对象数量的增加,这些检索可能会非常大,从而导致数据存储上出现不必要的负载,从而影响性能。
如果我使用 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 来检索图像对象。