2016-10-24 34 views
0

好吧,它聽起來很愚蠢,但我是MySQL新手,所以我真的不知道是否是聯接或其他的情況。如果用戶使用JPA和MySQL來檢查帖子是否被喜歡,最好的方法是什麼?

所以我有3個表,POST,USER,LIKES。基本上他們是:

POST 
post_id | caption | media | ... 

USER 
user_id | name  | email | ... 

LIKES 
like_id | post_id | user_id | ... 

而且在Java中的對象是:

@Entity 
@Table(name="POST") 
public class PostMW{ 

    @Id 
    @Column(name="id", nullable=false) 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private Long id; 

    @OneToOne(cascade = CascadeType.ALL) 
    @JoinColumn(name="media_id", nullable=false, unique=true) 
    private MediaMW media; 

    .... 

    @Transient 
    private Boolean liked; 

} 

而且喜歡:

@Entity 
@Table(name="LIKES") 
public class LikeMW { 

    @Id 
    @Column(name="id", nullable=false) 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private Long id; 

    @ManyToOne(cascade = CascadeType.ALL) 
    @JoinColumn(name = "post_id", nullable=false) 
    @JsonBackReference 
    private PostMW post; 

    @ManyToOne(cascade = CascadeType.ALL) 
    @JoinColumn(name="user_id", nullable=false) 
    private UserMW user; 

} 

的用戶可以請求POST的名單,所以我需要在設置如果該用戶喜歡,每個帖子都會「喜歡」這個屬性。

到目前爲止,我所做的:

public class FeedServiceImpl implements FeedService{ 
    private PostDao<PostMW, Long> postDao; 

    ... 

    @Override 
    public List<PostMW> getFeed(int page, UserMW user) { 
     List<PostMW> result; 
     int offset = page * ConstUtil.FEED_POSTS_PER_PAGE; 
     postDao.openCurrentSession(); 
     result = postDao.list(offset, ConstUtil.FEED_POSTS_PER_PAGE); 

     for(PostMW post : result){ 
      //TODO 
      //post.setLiked(postDao.postLikedByUser(post, user)); 

      //PS 
      // FOR EVERY POST I'M EXECUTING THE QUERY BELOW 

      //@NamedQuery(name="isLiked", query="SELECT COUNT(likes.id) FROM 
      //LikeMW likes WHERE likes.post.id = :postID AND likes.user.id = :userID"), 
     } 

     postDao.closeCurrentSession(); 

     return result; 
    } 

    ... 

} 

我甚至不知道,如果它的作品,因爲我真的不喜歡這個主意檢索例如100個職位,並在循環中,使100個請求排只是爲了檢查用戶是否喜歡這個帖子,所以我甚至沒有嘗試。

那麼,我該怎麼辦?任何建議將非常感謝!

謝謝!

編輯:

試圖在這個時刻查詢:

List<Object> result = entityManager 
       .createQuery("SELECT post FROM PostMW post LEFT OUTER JOIN post.hasLiked liked ON post.id = liked.post_id AND liked.user_id =:userID") 
       .setParameter("userID", 1) 
       .setFirstResult(offset).setMaxResults(itemsPerPage) 
       .getResultList(); 

更新我的對象。現在我PostMW對象有

@Entity 
@Table(name="POST") 
public class PostMW{ 
    ... 
    @ManyToMany(cascade = CascadeType.ALL) 
    @JoinTable(name="LIKES", [email protected](name="post_id"), [email protected](name="user_id")) 
    private List<UserMW> hasLiked; 
    ... 
} 

而且UserMW

@Entity 
@Table(name="USER") 
public class UserMW { 
    ... 
    @Id 
    @Column(name="id", nullable=false) 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private Long id; 

    @Column(name="name", nullable=false, length=255) 
    private String name; 
    ... 
} 

獲取此異常:

java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager: 
Exception Description: Internal problem encountered while compiling [SELECT post FROM PostMW post LEFT OUTER JOIN LikeMW likes ON post.id = likes.post_id AND likes.user_id =:userID]. 
Internal Exception: java.lang.NullPointerException 
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1605) 
at com.jonathan.myworld.model.dao.impl.PostDaoImpl.list(PostDaoImpl.java:72) 
at com.jonathan.myworld.service.impl.FeedServiceImpl.getFeed(FeedServiceImpl.java:45) 
at com.jonathan.myworld.UserWS.login(UserWS.java:151) 
at com.jonathan.myworld.UserWS.loginWithGoogle(UserWS.java:60) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
at java.lang.reflect.Method.invoke(Method.java:606) 
at com.google.appengine.tools.development.agent.runtime.Runtime.invoke(Runtime.java:130) 
at com.google.api.server.spi.SystemService.invokeServiceMethod(SystemService.java:363) 
at com.google.api.server.spi.SystemServiceServlet.execute(SystemServiceServlet.java:113) 
at com.google.api.server.spi.SystemServiceServlet.doPost(SystemServiceServlet.java:71) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) 
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) 
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) 
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166) 
at com.google.appengine.api.socket.dev.DevSocketFilter.doFilter(DevSocketFilter.java:74) 
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
at com.google.appengine.tools.development.ResponseRewriterFilter.doFilter(ResponseRewriterFilter.java:128) 
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
at com.google.appengine.tools.development.HeaderVerificationFilter.doFilter(HeaderVerificationFilter.java:34) 
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:63) 
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:50) 
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:125) 
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectRequest(DevAppServerModulesFilter.java:366) 
at com.google.appengine.tools.development.DevAppServerModulesFilter.doDirectModuleRequest(DevAppServerModulesFilter.java:349) 
at com.google.appengine.tools.development.DevAppServerModulesFilter.doFilter(DevAppServerModulesFilter.java:116) 
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157) 
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388) 
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) 
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) 
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765) 
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418) 
at com.google.appengine.tools.development.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:98) 
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:511) 
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
at org.mortbay.jetty.Server.handle(Server.java:326) 
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) 
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938) 
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755) 
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218) 
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) 
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409) 
at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) 
Caused by: Exception [EclipseLink-0] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.JPQLException 
Exception Description: Internal problem encountered while compiling [SELECT post FROM PostMW post LEFT OUTER JOIN LikeMW likes ON post.id = likes.post_id AND likes.user_id =:userID]. 
Internal Exception: java.lang.NullPointerException 
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.buildUnexpectedException(HermesParser.java:207) 
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.populateQueryImp(HermesParser.java:296) 
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.buildQuery(HermesParser.java:163) 
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:142) 
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.buildEJBQLDatabaseQuery(EJBQueryImpl.java:116) 
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:102) 
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.<init>(EJBQueryImpl.java:86) 
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1603) 
... 49 more 
Caused by: java.lang.NullPointerException 
at org.eclipse.persistence.queries.DatabaseQuery.addArgument(DatabaseQuery.java:449) 
at org.eclipse.persistence.queries.DatabaseQuery.addArgument(DatabaseQuery.java:419) 
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.addArguments(HermesParser.java:98) 
at org.eclipse.persistence.internal.jpa.jpql.HermesParser.populateQueryImp(HermesParser.java:287) 

回答

0

,你可以嘗試從帖子列表中提取喜歡的帖子你剛剛得到了。用「SELECT ... IN」請求),然後填充布爾isLiked;是這樣的:

... 

@Override 
public List<PostMW> getFeed(int page, UserMW user) { 
    List<PostMW> result; 
    int offset = page * ConstUtil.FEED_POSTS_PER_PAGE; 
    postDao.openCurrentSession(); 
    result = postDao.list(offset, ConstUtil.FEED_POSTS_PER_PAGE); 

    List<Long> postIds = new ArrayList(); 

    for(PostMW post : result){   
     postIds.add(post.getid(); 
    } 

    //then EXtract all liked post from list : 
    Query queryIn = em.createQuery("SELECT p.post.id FROM LikeMW p WHERE p.user = :user AND p.post IN :values"); 

    queryIn.setParameter("values", postIds); 
    queryIn.setParameter("user", currentUser); 
    List<Object[]> resultIn = queryIn.getResultList(); 

    Set<Long> postIdLiked) new HashSet<>(); 
    for(Object[] row: resultIn) { 
     postIdLiked.add(row[0]); 
    } 
    //then fill the boolean isLiked 
    for(PostMW post : result){    
     if (postIdLiked.contains(post.getId()) 
      post.setLiked(true);  
    } 

    postDao.closeCurrentSession(); 
    return result; 
} 

... 
+0

這可能是最好的答案,但仍,我就必須有2次數據庫調用(我忘了說我是從GAE調用亞馬遜RDS因此至少調用我這樣做會最好be),通過3個循環,每個循環可能有100個項目和一個「種類循環」在數據庫內... 希望有更好的方法。無論如何,謝謝你的答案。如果沒有人回覆,我會將其標記爲正確的。 –

相關問題