major improvement in the way data is stored

This commit is contained in:
Athou
2013-04-08 13:06:53 +02:00
parent 028982477e
commit cf7d4cce9c
14 changed files with 274 additions and 407 deletions

View File

@@ -19,7 +19,11 @@ import com.uaihebert.model.EasyCriteria;
public class FeedCategoryService extends GenericDAO<FeedCategory> {
public List<FeedCategory> findAll(User user) {
return findByField(MF.i(MF.p(FeedCategory.class).getUser()), user);
EasyCriteria<FeedCategory> criteria = createCriteria();
criteria.andEquals(MF.i(proxy().getUser()), user);
criteria.innerJoinFetch(MF.i(proxy().getUser()));
return criteria.getResultList();
}
public FeedCategory findById(User user, Long id) {

View File

@@ -3,27 +3,19 @@ package com.commafeed.backend.dao;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import org.apache.commons.lang.ObjectUtils;
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.FeedEntryStatus;
import com.commafeed.backend.model.FeedSubscription;
import com.commafeed.backend.model.User;
import com.commafeed.backend.model.extended.FeedEntryWithStatus;
import com.commafeed.frontend.utils.ModelFactory.MF;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
@Stateless
@SuppressWarnings("serial")
@@ -36,9 +28,7 @@ public class FeedEntryService extends GenericDAO<FeedEntry> {
FeedSubscriptionService feedSubscriptionService;
public void updateEntries(String url, Collection<FeedEntry> entries) {
Feed feed = Iterables.getFirst(
feedService.findByField(MF.i(MF.p(Feed.class).getUrl()), url),
null);
Feed feed = feedService.findByUrl(url);
List<String> guids = Lists.newArrayList();
for (FeedEntry entry : entries) {
guids.add(entry.getGuid());
@@ -56,7 +46,6 @@ public class FeedEntryService extends GenericDAO<FeedEntry> {
}
if (foundEntry == null) {
addFeedToEntry(entry, feed);
save(entry);
} else {
boolean foundFeed = false;
for (Feed existingFeed : foundEntry.getFeeds()) {
@@ -68,7 +57,6 @@ public class FeedEntryService extends GenericDAO<FeedEntry> {
if (!foundFeed) {
addFeedToEntry(foundEntry, feed);
update(foundEntry);
}
}
}
@@ -80,12 +68,13 @@ public class FeedEntryService extends GenericDAO<FeedEntry> {
private void addFeedToEntry(FeedEntry entry, Feed feed) {
entry.getFeeds().add(feed);
saveOrUpdate(entry);
List<FeedSubscription> subscriptions = feedSubscriptionService
.findByFeed(feed);
for (FeedSubscription sub : subscriptions) {
FeedEntryStatus status = new FeedEntryStatus();
status.setEntry(entry);
status.setUser(sub.getUser());
status.setSubscription(sub);
em.persist(status);
}
@@ -98,123 +87,4 @@ public class FeedEntryService extends GenericDAO<FeedEntry> {
return query.getResultList();
}
public List<FeedEntryWithStatus> getEntriesByKeywords(User user,
String keywords) {
return getEntriesByKeywords(user, keywords, -1, -1);
}
public List<FeedEntryWithStatus> getEntriesByKeywords(User user,
String keywords, int offset, int limit) {
Query query = em.createNamedQuery("Entry.allByKeywords");
query.setParameter("userId", user.getId());
query.setParameter("user", user);
String joinedKeywords = StringUtils.join(
keywords.toLowerCase().split(" "), "%");
query.setParameter("keywords", "%" + joinedKeywords + "%");
if (offset > -1) {
query.setFirstResult(offset);
}
if (limit > -1) {
query.setMaxResults(limit);
}
return buildList(query.getResultList());
}
public List<FeedEntryWithStatus> getEntries(User user, boolean unreadOnly) {
return getEntries(user, unreadOnly, -1, -1);
}
public List<FeedEntryWithStatus> getEntries(User user, boolean unreadOnly,
int offset, int limit) {
String queryName = null;
if (unreadOnly) {
queryName = "Entry.unread";
} else {
queryName = "Entry.all";
}
Query query = em.createNamedQuery(queryName);
query.setParameter("userId", user.getId());
query.setParameter("user", user);
if (offset > -1) {
query.setFirstResult(offset);
}
if (limit > -1) {
query.setMaxResults(limit);
}
return buildList(query.getResultList());
}
public Long getUnreadCount(Feed feed, User user) {
TypedQuery<Long> query = em.createNamedQuery("Entry.unreadByFeedCount",
Long.class);
query.setParameter("feed", feed);
query.setParameter("userId", user.getId());
return query.getSingleResult();
}
public List<FeedEntryWithStatus> getEntries(Feed feed, User user,
boolean unreadOnly) {
return getEntries(feed, user, unreadOnly, -1, -1);
}
public List<FeedEntryWithStatus> getEntries(Feed feed, User user,
boolean unreadOnly, int offset, int limit) {
String queryName = null;
if (unreadOnly) {
queryName = "Entry.unreadByFeed";
} else {
queryName = "Entry.allByFeed";
}
Query query = em.createNamedQuery(queryName);
query.setParameter("feed", feed);
query.setParameter("userId", user.getId());
if (offset > -1) {
query.setFirstResult(offset);
}
if (limit > -1) {
query.setMaxResults(limit);
}
return buildList(query.getResultList());
}
public List<FeedEntryWithStatus> getEntries(List<FeedCategory> categories,
User user, boolean unreadOnly) {
return getEntries(categories, user, unreadOnly, -1, -1);
}
public List<FeedEntryWithStatus> getEntries(List<FeedCategory> categories,
User user, boolean unreadOnly, int offset, int limit) {
String queryName = null;
if (unreadOnly) {
queryName = "Entry.unreadByCategories";
} else {
queryName = "Entry.allByCategories";
}
Query query = em.createNamedQuery(queryName);
query.setParameter("categories", categories);
query.setParameter("userId", user.getId());
query.setParameter("user", user);
if (offset > -1) {
query.setFirstResult(offset);
}
if (limit > -1) {
query.setMaxResults(limit);
}
return buildList(query.getResultList());
}
@SuppressWarnings("rawtypes")
private List<FeedEntryWithStatus> buildList(List list) {
Set<FeedEntryWithStatus> result = Sets.newLinkedHashSet();
for (Object object : list) {
Object[] array = (Object[]) object;
FeedEntry entry = (FeedEntry) array[0];
FeedEntryStatus status = (FeedEntryStatus) array[1];
FeedEntryWithStatus fews = new FeedEntryWithStatus(entry, status);
result.add(fews);
}
return Lists.newArrayList(result);
}
}

View File

@@ -1,37 +1,172 @@
package com.commafeed.backend.dao;
import java.util.List;
import java.util.Map;
import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import com.commafeed.backend.model.FeedEntry;
import org.apache.commons.lang.StringUtils;
import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedCategory;
import com.commafeed.backend.model.FeedEntryStatus;
import com.commafeed.backend.model.User;
import com.commafeed.frontend.utils.ModelFactory.MF;
import com.uaihebert.factory.EasyCriteriaFactory;
import com.uaihebert.model.EasyCriteria;
import com.google.api.client.util.Lists;
import com.google.api.client.util.Maps;
@Stateless
@SuppressWarnings("serial")
public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus> {
public List<FeedEntryStatus> findAll(User user) {
return findByField(MF.i(proxy().getUser()), user);
}
@Inject
FeedCategoryService feedCategoryService;
public FeedEntryStatus getStatus(User user, FeedEntry entry) {
EasyCriteria<FeedEntryStatus> criteria = EasyCriteriaFactory
.createQueryCriteria(em, getType());
criteria.andEquals(MF.i(proxy().getUser()), user);
criteria.andEquals(MF.i(proxy().getEntry()), entry);
public FeedEntryStatus findById(User user, Long id) {
TypedQuery<FeedEntryStatus> query = em.createNamedQuery(
"EntryStatus.byId", FeedEntryStatus.class);
query.setParameter("user", user);
query.setParameter("id", id);
FeedEntryStatus status = null;
try {
status = criteria.getSingleResult();
status = query.getSingleResult();
} catch (NoResultException e) {
status = null;
}
return status;
}
public List<FeedEntryStatus> getStatusesByKeywords(User user,
String keywords) {
return getStatusesByKeywords(user, keywords, -1, -1);
}
public List<FeedEntryStatus> getStatusesByKeywords(User user,
String keywords, int offset, int limit) {
TypedQuery<FeedEntryStatus> query = em.createNamedQuery(
"EntryStatus.allByKeywords", FeedEntryStatus.class);
query.setParameter("user", user);
String joinedKeywords = StringUtils.join(
keywords.toLowerCase().split(" "), "%");
query.setParameter("keywords", "%" + joinedKeywords + "%");
if (offset > -1) {
query.setFirstResult(offset);
}
if (limit > -1) {
query.setMaxResults(limit);
}
return query.getResultList();
}
public List<FeedEntryStatus> getStatuses(User user, boolean unreadOnly) {
return getStatuses(user, unreadOnly, -1, -1);
}
public List<FeedEntryStatus> getStatuses(User user, boolean unreadOnly,
int offset, int limit) {
String queryName = unreadOnly ? "EntryStatus.unread"
: "EntryStatus.all";
TypedQuery<FeedEntryStatus> query = em.createNamedQuery(queryName,
FeedEntryStatus.class);
query.setParameter("user", user);
if (offset > -1) {
query.setFirstResult(offset);
}
if (limit > -1) {
query.setMaxResults(limit);
}
return query.getResultList();
}
/**
* Map between subscriptionId and unread count
*/
@SuppressWarnings("rawtypes")
public Map<Long, Long> getUnreadCount(User user) {
Map<Long, Long> map = Maps.newHashMap();
Query query = em.createNamedQuery("EntryStatus.unreadCounts");
query.setParameter("user", user);
List resultList = query.getResultList();
for (Object o : resultList) {
Object[] array = (Object[]) o;
map.put((Long) array[0], (Long) array[1]);
}
return map;
}
public List<FeedEntryStatus> getStatuses(Feed feed, User user,
boolean unreadOnly) {
return getStatuses(feed, user, unreadOnly, -1, -1);
}
public List<FeedEntryStatus> getStatuses(Feed feed, User user,
boolean unreadOnly, int offset, int limit) {
String queryName = unreadOnly ? "EntryStatus.unreadByFeed"
: "EntryStatus.allByFeed";
TypedQuery<FeedEntryStatus> query = em.createNamedQuery(queryName,
FeedEntryStatus.class);
query.setParameter("feed", feed);
query.setParameter("user", user);
if (offset > -1) {
query.setFirstResult(offset);
}
if (limit > -1) {
query.setMaxResults(limit);
}
return query.getResultList();
}
public List<FeedEntryStatus> getStatuses(List<FeedCategory> categories,
User user, boolean unreadOnly) {
return getStatuses(categories, user, unreadOnly, -1, -1);
}
public List<FeedEntryStatus> getStatuses(List<FeedCategory> categories,
User user, boolean unreadOnly, int offset, int limit) {
String queryName = unreadOnly ? "EntryStatus.unreadByCategories"
: "EntryStatus.allByCategories";
TypedQuery<FeedEntryStatus> query = em.createNamedQuery(queryName,
FeedEntryStatus.class);
query.setParameter("categories", categories);
query.setParameter("user", user);
if (offset > -1) {
query.setFirstResult(offset);
}
if (limit > -1) {
query.setMaxResults(limit);
}
return query.getResultList();
}
public void markFeedEntries(User user, Feed feed) {
List<FeedEntryStatus> statuses = getStatuses(feed, user, true);
update(markList(statuses));
}
public void markCategoryEntries(User user, List<FeedCategory> categories) {
List<FeedEntryStatus> statuses = getStatuses(categories, user, true);
update(markList(statuses));
}
public void markAllEntries(User user) {
List<FeedEntryStatus> statuses = getStatuses(user, true);
update(markList(statuses));
}
private List<FeedEntryStatus> markList(List<FeedEntryStatus> statuses) {
List<FeedEntryStatus> list = Lists.newArrayList();
for (FeedEntryStatus status : statuses) {
if (!status.isRead()) {
status.setRead(true);
list.add(status);
}
}
return list;
}
}

View File

@@ -41,7 +41,13 @@ public class FeedSubscriptionService extends GenericDAO<FeedSubscription> {
}
public List<FeedSubscription> findAll(User user) {
return findByField(MF.i(proxy().getUser()), user);
EasyCriteria<FeedSubscription> criteria = createCriteria();
criteria.andEquals(MF.i(proxy().getUser()), user);
criteria.innerJoinFetch(MF.i(proxy().getFeed()));
criteria.innerJoinFetch(MF.i(proxy().getUser()));
criteria.leftJoinFetch(MF.i(proxy().getCategory()));
return criteria.getResultList();
}
public List<FeedSubscription> findWithoutCategories(User user) {

View File

@@ -1,6 +1,7 @@
package com.commafeed.backend.dao;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import javax.annotation.PostConstruct;
@@ -37,12 +38,16 @@ public abstract class GenericDAO<T extends AbstractModel> implements
em.persist(object);
}
public void update(T... objects) {
public void update(List<T> objects) {
for (Object object : objects) {
em.merge(object);
}
}
public void update(T... objects) {
update(Arrays.asList(objects));
}
public void saveOrUpdate(AbstractModel m) {
if (m.getId() == null) {
em.persist(m);

View File

@@ -13,7 +13,7 @@ public class FeedEntryStatus extends AbstractModel {
@ManyToOne
@JoinColumn(nullable = false)
private User user;
private FeedSubscription subscription;
@ManyToOne
@JoinColumn(nullable = false)
@@ -23,12 +23,12 @@ public class FeedEntryStatus extends AbstractModel {
private boolean read;
private boolean starred;
public User getUser() {
return user;
public FeedSubscription getSubscription() {
return subscription;
}
public void setUser(User user) {
this.user = user;
public void setSubscription(FeedSubscription subscription) {
this.subscription = subscription;
}
public FeedEntry getEntry() {

View File

@@ -1,59 +0,0 @@
package com.commafeed.backend.model.extended;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import com.commafeed.backend.model.FeedEntry;
import com.commafeed.backend.model.FeedEntryStatus;
public class FeedEntryWithStatus {
private FeedEntry entry;
private FeedEntryStatus status;
public FeedEntryWithStatus(FeedEntry entry, FeedEntryStatus status) {
this.entry = entry;
this.status = status;
}
@Override
public int hashCode() {
return new HashCodeBuilder(17, 37).append(entry.getId())
.append(status == null ? null : status.getId()).toHashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj == this) {
return true;
}
if (obj.getClass() != getClass()) {
return false;
}
FeedEntryWithStatus rhs = (FeedEntryWithStatus) obj;
return new EqualsBuilder()
.append(status == null ? null : status.getId(),
rhs.status == null ? null : rhs.status.getId())
.append(entry.getId(), rhs.entry.getId()).isEquals();
}
public FeedEntry getEntry() {
return entry;
}
public void setEntry(FeedEntry entry) {
this.entry = entry;
}
public FeedEntryStatus getStatus() {
return status;
}
public void setStatus(FeedEntryStatus status) {
this.status = status;
}
}