2011-10-29 35 views
1

我正在創建一種像Facebook這樣的社交網站,作爲一個大學項目。用戶可以上傳照片,但我無法檢索特定用戶的照片列表。JPA - 如何避免獲取空列表?

以下是我正在做它現在:

@Entity 
@Table(name = "users") 
public class User implements Serializable { 

@Id 
private String emailAddress; 
private String password; 
private String firstName; 
private String lastName; 

(...) 

@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER) 
private List<Photo> photos; 

public User() { 
} 

(...) 

public void addPhoto(Photo photo){ 
    photos.add(photo); 
} 

public List<Photo> getPhotos() { 
    return photos; 
} 
} 

而這裏的照片實體:

@Entity 
public class Photo implements Serializable { 
@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Long id; 
private String url; 
private String label;  
@ManyToOne 
private User owner; 

public Photo() { 
} 

(...) 

public User getOwner() { 
    return owner; 
}  
} 

每張照片是通過創建一個包含它的後上傳。下面是做它的EJB:

@Stateless 
public class PublicPost implements PublicPostRemote { 

@PersistenceContext 
EntityManager em; 

@Override 
public void createPost(LoginUserRemote loginUserBean, String targetEmail, final String content, final String photoURL) { 
    if (loginUserBean.isLoggedIn()) { 
     final User author = loginUserBean.getLoggedUser(); 
     System.out.println(targetEmail); 
     final User target = em.find(User.class, targetEmail); 
     if (author != null && target != null) { 
      //See if there's a photo to post as well 
      Photo photo = null; 
      if (photoURL != null) { 
       photo = new Photo(photoURL, author, content); 
       em.persist(photo); 
      } 

      MessageBoard publicMessageBoard = target.getPublicMessageBoard(); 
      Post post = new Post(author, content); 
      post.setMessageBoard(publicMessageBoard); 
      if (photo != null) { 
       post.setPostPhoto(photo); 
      } 
      em.persist(post); 
      em.refresh(publicMessageBoard); 
      //Send an e-mail to the target (if the author and the target are different) 
      if (!author.getEmailAddress().equals(target.getEmailAddress())) { 
       final String subject = "[PhaseBook] " + author.getEmailAddress() + " has posted on your public message board."; 
       Thread mailThread = new Thread() { 

        @Override 
        public void run() { 
         try { 
          GMailSender.sendMessage(target.getEmailAddress(), subject, content); 
         } catch (MessagingException ex) { 
          Logger.getLogger(PublicPost.class.getName()).log(Level.SEVERE, null, ex); 
         } 
        } 
       }; 
       mailThread.start(); 
      } 
     } 
    } 
} 
} 

那麼什麼情況是:我創建一個包含照片,再稍後一個新的職位,當我用這個,在Web層...

LoginUserRemote lur = (LoginUserRemote)session.getAttribute("loginUserBean"); 
User user = lur.getLoggedUser(); 
List<Photo> photos = user.getPhotos(); 
System.out.println(); 
System.out.println("This user has this many photos: " + photos.size()); 

...它總是告訴我,用戶有0張照片。爲什麼是這樣?我是否錯誤地定義了用戶和照片之間的關係?我忘了堅持/刷新任何東西嗎?還是問題在別的地方?

回答

0

有一系列的問題在這裏:

  • 照片是否實際存儲在數據庫中?也許你沒有開放交易?

  • 您不更新關聯的雙方。

理論上你只需要更新的擁有方,但更好的安全比遺憾:

photo = new Photo(photoURL, author, content); 
em.persist(photo); 
author.addPhoto(photo); 
  • 您獲取從會話的用戶,然後檢索的照片相關的集合。你真的知道這意味着什麼嗎?如果用戶有數百張照片,您是否真的想將它們始終與用戶一起存儲在HTTP會話中?這不是Facebook的工作方式;-)。

認爲刷新你的實體(與em.refresh(lur.getLoggedUser()))可能會奏效,但只有在大學,而不是真實的生活。一次將所有用戶照片加載到內存中是一個矯枉過正的行爲。我個人甚至會刪除用戶的photos關聯以避免這種情況。一次只能按需加載一個頁面。

  • 即使你知道你在做什麼,或者這樣的行爲是可以接受的,存儲在HTTP會話對象是所謂的持久化上下文分離,這意味着你的持久性提供者不再對其進行跟蹤。因此,添加照片並不意味着每個對象都會神奇地更新集合。我仔細想想,情況會更糟。

  • 最後但並非最不重要,您的createPost()真的需要一些代碼審查。它一次至少執行4件事,System.out,一次性線程按需創建,當不滿足預設條件時(如用戶未登錄,缺少參數)靜靜地無所事事,混合不同抽象級別的問題。不要太細緻,但是您的成績可能會受到代碼質量的影響。

1

如果存儲分離的用戶對象(登錄的用戶)在HTTP會話,然後創建並具有這種分離的用戶作爲所有者仍然存在的照片,JPA不會自動添加的照片到分離的用戶。對於實體經理,這個分離的用戶不存在:它不再是它的責任。

即使用戶仍連接,這是你的責任,以保持對象圖的一致性。如果修改關聯的一側(通過將用戶設置爲照片的所有者),還應該修改另一側(將照片添加到所有者的照片列表中)。

我沒有絕對的把握,這是問題的原因,因爲你還沒有告訴我們什麼loginUserBean是並沒有獲得登錄的用戶,但它可能是答案。