我有以下具有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
字段表照片使用FK建立寵物之間1-N的關係(1)和圖片(N)。字段對象圖像在Photo中是一個序列化的圖像對象。
對於數據存儲區操作我使用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張照片。
但是,當我分析的DataNucleus日誌爲petDao.storePhoto((long)0,photo)代碼,我看到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 "[email protected]6"
Persist [DEBUG] Object "[email protected]" 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
添加了 「照片4」 使用INSERT INTO照片...語句之後,DataNucleus將通過發射3 SELECT映像從PHOTO語句檢索前面三個圖像對象。 隨着圖像對象數量的增加,這些檢索可能會相當大,從而導致數據存儲上不必要的負載影響性能。
如果我使用pm.getObjectById()選擇寵物,並分離寵物對象並將照片添加到分離的對象,然後用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((長)0,照片)或在PetDao.storePhoto方法使用PMF的一個單獨的實例,然後DataNucleus將將不發射SELECT到檢索圖像對象。
爲了便於理解,我給了PET/Photo示例。這個問題更多的是關於JDO優化和延遲加載,而不是對象建模。 1到N構造是一種經常使用的關係,JDO/DataNucleus通過在應用程序實際訪問對象時延遲加載對象來很好地處理它。正如我在上次觀察中提到的那樣,DataNucleus在從不同PMF發射照片對象時不會加載照片對象。所以,我更感興趣的是知道爲什麼DataNucleus在應用程序代碼沒有訪問它們(即照片對象)時正在獲取Photo對象。 – Maithilish
Pet.addPhoto()不可避免地會訪問pet.photos列表來添加一個,這將觸發列表中所有元素的獲取。我不知道有什麼方法與列表映射。 – TheArchitect
是的,我同意,它必須獲取列表中的所有元素。因此,它將加載列表的所有照片,但它只能檢索Photo.id和Photo.desc字段(因爲它們屬於默認提取組),並推遲加載Photo.image字段(JDO的延遲加載功能)直到圖像被應用程序代碼訪問,因爲它不屬於默認獲取組。當您逐一檢索寵物並訪問圖像時,Photo.image字段的延遲加載完全按預期發生。只有當您持續一個新的Pet,然後在同一會話(或PMF)中調用Pet.addPhoto()時,纔會急於加載圖像表面。 – Maithilish