From 993bc0a1acb77be19b942591d90acbf2a653d01d Mon Sep 17 00:00:00 2001 From: Athou Date: Wed, 15 May 2013 16:01:14 +0200 Subject: [PATCH] left joins instead of cross joins --- .../backend/dao/FeedEntryStatusDAO.java | 113 ++++++++++++------ .../backend/dao/FeedSubscriptionDAO.java | 1 + .../frontend/rest/resources/EntryREST.java | 2 +- 3 files changed, 79 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/commafeed/backend/dao/FeedEntryStatusDAO.java b/src/main/java/com/commafeed/backend/dao/FeedEntryStatusDAO.java index 960b8fa9..5a101478 100644 --- a/src/main/java/com/commafeed/backend/dao/FeedEntryStatusDAO.java +++ b/src/main/java/com/commafeed/backend/dao/FeedEntryStatusDAO.java @@ -9,6 +9,8 @@ import javax.persistence.NoResultException; import javax.persistence.Query; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; @@ -17,10 +19,13 @@ import org.apache.commons.lang.StringUtils; import com.commafeed.backend.model.Feed; import com.commafeed.backend.model.FeedCategory; +import com.commafeed.backend.model.FeedEntry; +import com.commafeed.backend.model.FeedEntryContent; import com.commafeed.backend.model.FeedEntryContent_; import com.commafeed.backend.model.FeedEntryStatus; import com.commafeed.backend.model.FeedEntryStatus_; import com.commafeed.backend.model.FeedEntry_; +import com.commafeed.backend.model.FeedSubscription; import com.commafeed.backend.model.FeedSubscription_; import com.commafeed.backend.model.User; import com.commafeed.backend.model.UserSettings.ReadingOrder; @@ -51,8 +56,9 @@ public class FeedEntryStatusDAO extends GenericDAO { return status; } + @SuppressWarnings("unchecked") public List findByKeywords(User user, String keywords, - int offset, int limit, boolean includeContent) { + int offset, int limit) { String joinedKeywords = StringUtils.join( keywords.toLowerCase().split(" "), "%"); @@ -62,30 +68,37 @@ public class FeedEntryStatusDAO extends GenericDAO { Root root = query.from(getType()); List predicates = Lists.newArrayList(); - predicates.add(builder.equal(root.get(FeedEntryStatus_.subscription) - .get(FeedSubscription_.user), user)); - Predicate content = builder.like(builder.lower(root - .get(FeedEntryStatus_.entry).get(FeedEntry_.content) - .get(FeedEntryContent_.content)), joinedKeywords); + Join subJoin = root.join( + FeedEntryStatus_.subscription, JoinType.LEFT); + subJoin.join(FeedSubscription_.category, JoinType.LEFT); + + Join entryJoin = (Join) root + .fetch(FeedEntryStatus_.entry, JoinType.LEFT); + Join contentJoin = (Join) entryJoin + .fetch(FeedEntry_.content, JoinType.LEFT); + + predicates + .add(builder.equal(subJoin.get(FeedSubscription_.user), user)); + + Predicate content = builder.like( + builder.lower(contentJoin.get(FeedEntryContent_.content)), + joinedKeywords); Predicate title = builder.like( - builder.lower(root.get(FeedEntryStatus_.entry) - .get(FeedEntry_.content).get(FeedEntryContent_.title)), + builder.lower(contentJoin.get(FeedEntryContent_.title)), joinedKeywords); predicates.add(builder.or(content, title)); - if (includeContent) { - root.fetch(FeedEntryStatus_.entry).fetch(FeedEntry_.content); - } query.where(predicates.toArray(new Predicate[0])); - orderBy(query, root, ReadingOrder.desc); + orderBy(query, entryJoin, ReadingOrder.desc); TypedQuery q = em.createQuery(query); limit(q, offset, limit); return q.getResultList(); } + @SuppressWarnings("unchecked") public List findStarred(User user, int offset, int limit, ReadingOrder order, boolean includeContent) { @@ -93,15 +106,22 @@ public class FeedEntryStatusDAO extends GenericDAO { Root root = query.from(getType()); List predicates = Lists.newArrayList(); - predicates.add(builder.equal(root.get(FeedEntryStatus_.subscription) - .get(FeedSubscription_.user), user)); + + Join subJoin = root.join( + FeedEntryStatus_.subscription, JoinType.LEFT); + subJoin.join(FeedSubscription_.category, JoinType.LEFT); + Join entryJoin = (Join) root + .fetch(FeedEntryStatus_.entry, JoinType.LEFT); + + predicates + .add(builder.equal(subJoin.get(FeedSubscription_.user), user)); predicates.add(builder.equal(root.get(FeedEntryStatus_.starred), true)); query.where(predicates.toArray(new Predicate[0])); if (includeContent) { - root.fetch(FeedEntryStatus_.entry).fetch(FeedEntry_.content); + entryJoin.fetch(FeedEntry_.content, JoinType.LEFT); } - orderBy(query, root, order); + orderBy(query, entryJoin, order); TypedQuery q = em.createQuery(query); limit(q, offset, limit); @@ -113,24 +133,32 @@ public class FeedEntryStatusDAO extends GenericDAO { return findAll(user, unreadOnly, -1, -1, order, includeContent); } + @SuppressWarnings("unchecked") public List findAll(User user, boolean unreadOnly, int offset, int limit, ReadingOrder order, boolean includeContent) { CriteriaQuery query = builder.createQuery(getType()); Root root = query.from(getType()); List predicates = Lists.newArrayList(); - predicates.add(builder.equal(root.get(FeedEntryStatus_.subscription) - .get(FeedSubscription_.user), user)); + + Join subJoin = root.join( + FeedEntryStatus_.subscription, JoinType.LEFT); + subJoin.join(FeedSubscription_.category, JoinType.LEFT); + Join entryJoin = (Join) root + .fetch(FeedEntryStatus_.entry, JoinType.LEFT); + + predicates + .add(builder.equal(subJoin.get(FeedSubscription_.user), user)); if (unreadOnly) { predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read))); } if (includeContent) { - root.fetch(FeedEntryStatus_.entry).fetch(FeedEntry_.content); + entryJoin.fetch(FeedEntry_.content, JoinType.LEFT); } query.where(predicates.toArray(new Predicate[0])); - orderBy(query, root, order); + orderBy(query, entryJoin, order); TypedQuery q = em.createQuery(query); limit(q, offset, limit); @@ -158,6 +186,7 @@ public class FeedEntryStatusDAO extends GenericDAO { return findByFeed(feed, user, unreadOnly, -1, -1, order, includeContent); } + @SuppressWarnings("unchecked") public List findByFeed(Feed feed, User user, boolean unreadOnly, int offset, int limit, ReadingOrder order, boolean includeContent) { @@ -166,21 +195,28 @@ public class FeedEntryStatusDAO extends GenericDAO { Root root = query.from(getType()); List predicates = Lists.newArrayList(); - predicates.add(builder.equal(root.get(FeedEntryStatus_.subscription) - .get(FeedSubscription_.user), user)); - predicates.add(builder.equal(root.get(FeedEntryStatus_.subscription) - .get(FeedSubscription_.feed), feed)); + + Join subJoin = root.join( + FeedEntryStatus_.subscription, JoinType.LEFT); + subJoin.join(FeedSubscription_.category, JoinType.LEFT); + Join entryJoin = (Join) root + .fetch(FeedEntryStatus_.entry, JoinType.LEFT); + + predicates + .add(builder.equal(subJoin.get(FeedSubscription_.user), user)); + predicates + .add(builder.equal(subJoin.get(FeedSubscription_.feed), feed)); if (unreadOnly) { predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read))); } if (includeContent) { - root.fetch(FeedEntryStatus_.entry).fetch(FeedEntry_.content); + entryJoin.fetch(FeedEntry_.content, JoinType.LEFT); } query.where(predicates.toArray(new Predicate[0])); - orderBy(query, root, order); + orderBy(query, entryJoin, order); TypedQuery q = em.createQuery(query); limit(q, offset, limit); @@ -194,6 +230,7 @@ public class FeedEntryStatusDAO extends GenericDAO { includeContent); } + @SuppressWarnings("unchecked") public List findByCategories( List categories, User user, boolean unreadOnly, int offset, int limit, ReadingOrder order, boolean includeContent) { @@ -202,21 +239,27 @@ public class FeedEntryStatusDAO extends GenericDAO { Root root = query.from(getType()); List predicates = Lists.newArrayList(); - predicates.add(builder.equal(root.get(FeedEntryStatus_.subscription) - .get(FeedSubscription_.user), user)); - predicates.add(root.get(FeedEntryStatus_.subscription) - .get(FeedSubscription_.category).in(categories)); + + Join subJoin = root.join( + FeedEntryStatus_.subscription, JoinType.LEFT); + subJoin.join(FeedSubscription_.category, JoinType.LEFT); + Join entryJoin = (Join) root + .fetch(FeedEntryStatus_.entry, JoinType.LEFT); + + predicates + .add(builder.equal(subJoin.get(FeedSubscription_.user), user)); + predicates.add(subJoin.get(FeedSubscription_.category).in(categories)); if (unreadOnly) { predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read))); } if (includeContent) { - root.fetch(FeedEntryStatus_.entry).fetch(FeedEntry_.content); + entryJoin.fetch(FeedEntry_.content, JoinType.LEFT); } query.where(predicates.toArray(new Predicate[0])); - orderBy(query, root, order); + orderBy(query, entryJoin, order); TypedQuery q = em.createQuery(query); limit(q, offset, limit); @@ -224,15 +267,13 @@ public class FeedEntryStatusDAO extends GenericDAO { } private void orderBy(CriteriaQuery query, - Root root, ReadingOrder order) { - Path orderPath = root.get(FeedEntryStatus_.entry).get( - FeedEntry_.updated); + Join entryJoin, ReadingOrder order) { + Path orderPath = entryJoin.get(FeedEntry_.updated); if (order == ReadingOrder.asc) { query.orderBy(builder.asc(orderPath)); } else { query.orderBy(builder.desc(orderPath)); } - } public void markFeedEntries(User user, Feed feed, Date olderThan) { diff --git a/src/main/java/com/commafeed/backend/dao/FeedSubscriptionDAO.java b/src/main/java/com/commafeed/backend/dao/FeedSubscriptionDAO.java index c5b68b3b..f9319083 100644 --- a/src/main/java/com/commafeed/backend/dao/FeedSubscriptionDAO.java +++ b/src/main/java/com/commafeed/backend/dao/FeedSubscriptionDAO.java @@ -22,6 +22,7 @@ public class FeedSubscriptionDAO extends GenericDAO { criteria.andEquals(FeedSubscription_.id.getName(), id); criteria.leftJoinFetch(FeedSubscription_.feed.getName()); criteria.leftJoinFetch(FeedSubscription_.user.getName()); + criteria.leftJoinFetch(FeedSubscription_.category.getName()); return Iterables.getFirst(criteria.getResultList(), null); } diff --git a/src/main/java/com/commafeed/frontend/rest/resources/EntryREST.java b/src/main/java/com/commafeed/frontend/rest/resources/EntryREST.java index 2faf4f84..de437989 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/EntryREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/EntryREST.java @@ -69,7 +69,7 @@ public class EntryREST extends AbstractResourceREST { List list = Lists.newArrayList(); List entriesStatus = feedEntryStatusDAO - .findByKeywords(getUser(), keywords, offset, limit, true); + .findByKeywords(getUser(), keywords, offset, limit); for (FeedEntryStatus status : entriesStatus) { list.add(Entry.build(status)); }