From b20b1239a0b6aba0f847c3bed228b2145c9491c9 Mon Sep 17 00:00:00 2001 From: Tom Zhao <tom.zhao@dsv.su.se> Date: Wed, 18 Dec 2024 13:23:58 +0100 Subject: [PATCH] 3470: Refactor how message counting works: 1. Now we retrieve at first all threads, then use another database call to get count of threads which have unread posts. It makes possible to reuse the logic of unread-post-counting somewhere else. 2. We use QueryDSL instead of native SQL, also left join from thread table instead of exists(). --- .../dsv/scipro/forum/BasicForumService.java | 1 + .../scipro/forum/BasicForumServiceImpl.java | 5 +++ .../dsv/scipro/forum/ForumPostRepository.java | 3 ++ .../scipro/forum/ForumPostRepositoryImpl.java | 19 +++++++++++ .../scipro/forum/ProjectForumServiceImpl.java | 15 +++------ .../scipro/forum/ProjectThreadRepository.java | 7 ++-- .../forum/ProjectThreadRepositoryImpl.java | 33 +++---------------- 7 files changed, 38 insertions(+), 45 deletions(-) diff --git a/core/src/main/java/se/su/dsv/scipro/forum/BasicForumService.java b/core/src/main/java/se/su/dsv/scipro/forum/BasicForumService.java index a6cff8bdae..b1001c6a3b 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/BasicForumService.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/BasicForumService.java @@ -23,4 +23,5 @@ public interface BasicForumService extends Serializable { ForumThread createThread(String subject); + long countUnreadThreads(List<ForumThread> forumThreadList, User user); } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/BasicForumServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/forum/BasicForumServiceImpl.java index 0dae3383bb..6877c784ae 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/BasicForumServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/BasicForumServiceImpl.java @@ -88,6 +88,11 @@ public class BasicForumServiceImpl implements BasicForumService { return threadRepository.save(forumThread); } + @Override + public long countUnreadThreads(List<ForumThread> forumThreadList, User user) { + return postRepository.countUnreadThreads(forumThreadList, user); + } + private ForumPostReadState getReadState(final User user, final ForumPost post) { ForumPostReadState state = readStateRepository.find(user, post); if (state == null) { diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ForumPostRepository.java b/core/src/main/java/se/su/dsv/scipro/forum/ForumPostRepository.java index 92e3afb1c8..8e965c015b 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/ForumPostRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/ForumPostRepository.java @@ -7,6 +7,7 @@ import se.su.dsv.scipro.forum.dataobjects.ForumPost; import se.su.dsv.scipro.forum.dataobjects.ForumThread; import se.su.dsv.scipro.forum.dataobjects.ProjectThread; import se.su.dsv.scipro.project.Project; +import se.su.dsv.scipro.system.User; import se.su.dsv.scipro.util.Pair; import java.util.List; @@ -17,4 +18,6 @@ public interface ForumPostRepository extends JpaRepository<ForumPost, Long>, Que List<ForumPost> findByThread(ForumThread forumThread); List<Pair<ProjectThread, ForumPost>> latestPost(Project project, int amount); + + long countUnreadThreads(List<ForumThread> forumThreadList, User user); } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ForumPostRepositoryImpl.java b/core/src/main/java/se/su/dsv/scipro/forum/ForumPostRepositoryImpl.java index e4536e7582..e806c717d6 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/ForumPostRepositoryImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/ForumPostRepositoryImpl.java @@ -1,15 +1,19 @@ package se.su.dsv.scipro.forum; +import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQuery; import jakarta.persistence.EntityManager; +import jakarta.persistence.Query; import se.su.dsv.scipro.forum.dataobjects.ForumPost; import se.su.dsv.scipro.forum.dataobjects.ForumThread; import se.su.dsv.scipro.forum.dataobjects.ProjectThread; import se.su.dsv.scipro.forum.dataobjects.QForumPost; +import se.su.dsv.scipro.forum.dataobjects.QForumPostReadState; import se.su.dsv.scipro.forum.dataobjects.QForumThread; import se.su.dsv.scipro.forum.dataobjects.QProjectThread; import se.su.dsv.scipro.project.Project; import se.su.dsv.scipro.system.GenericRepo; +import se.su.dsv.scipro.system.User; import se.su.dsv.scipro.util.Pair; import jakarta.inject.Inject; @@ -46,4 +50,19 @@ public class ForumPostRepositoryImpl extends GenericRepo<ForumPost, Long> implem tuple.get(QForumPost.forumPost))) .toList(); } + + @Override + public long countUnreadThreads(List<ForumThread> forumThreadList, User user) { + return new JPAQuery<>(em()) + .select(QForumThread.forumThread.id.countDistinct()) + .from(QForumThread.forumThread) + .leftJoin(QForumThread.forumThread.posts, QForumPost.forumPost) + .where(QForumPost.forumPost.notIn( + JPAExpressions.select(QForumPostReadState.forumPostReadState.id.post) + .from(QForumPostReadState.forumPostReadState) + .where(QForumPostReadState.forumPostReadState.read.isTrue(), + QForumPostReadState.forumPostReadState.id.user.eq(user)) + ), QForumThread.forumThread.in(forumThreadList) + ).fetchOne(); + } } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java b/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java index 467b092b70..305943b062 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/ProjectForumServiceImpl.java @@ -108,18 +108,11 @@ public class ProjectForumServiceImpl implements ProjectForumService { @Override public long getUnreadThreadsCount(Project project, User user) { - return projectThreadRepository.getUnreadThreadsCount(project, user); - /* List<ProjectThread> threads = getThreads(project); - int count = 0; - for (ProjectThread thread : threads) { - if (!basicForumService.isThreadRead(user, thread.getForumThread())) { - count++; - } - } - return count; - - */ + List<ForumThread> list = threads.stream() + .map(ProjectThread::getForumThread) + .toList(); + return basicForumService.countUnreadThreads(list, user); } @Override diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ProjectThreadRepository.java b/core/src/main/java/se/su/dsv/scipro/forum/ProjectThreadRepository.java index 189ffed09b..83720860fe 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/ProjectThreadRepository.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/ProjectThreadRepository.java @@ -1,11 +1,10 @@ package se.su.dsv.scipro.forum; import jakarta.transaction.Transactional; -import se.su.dsv.scipro.system.JpaRepository; -import se.su.dsv.scipro.system.QueryDslPredicateExecutor; import se.su.dsv.scipro.forum.dataobjects.ProjectThread; import se.su.dsv.scipro.project.Project; -import se.su.dsv.scipro.system.User; +import se.su.dsv.scipro.system.JpaRepository; +import se.su.dsv.scipro.system.QueryDslPredicateExecutor; import java.util.List; @@ -14,6 +13,4 @@ public interface ProjectThreadRepository extends JpaRepository<ProjectThread, Lo List<ProjectThread> findByProject(Project project); - long getUnreadThreadsCount(Project project, User user); - } diff --git a/core/src/main/java/se/su/dsv/scipro/forum/ProjectThreadRepositoryImpl.java b/core/src/main/java/se/su/dsv/scipro/forum/ProjectThreadRepositoryImpl.java index 26286262e6..cf5988cfde 100644 --- a/core/src/main/java/se/su/dsv/scipro/forum/ProjectThreadRepositoryImpl.java +++ b/core/src/main/java/se/su/dsv/scipro/forum/ProjectThreadRepositoryImpl.java @@ -1,15 +1,12 @@ package se.su.dsv.scipro.forum; -import jakarta.persistence.Query; -import se.su.dsv.scipro.forum.dataobjects.ProjectThread; -import se.su.dsv.scipro.forum.dataobjects.QProjectThread; -import se.su.dsv.scipro.project.Project; -import se.su.dsv.scipro.system.GenericRepo; - import jakarta.inject.Inject; import jakarta.inject.Provider; import jakarta.persistence.EntityManager; -import se.su.dsv.scipro.system.User; +import se.su.dsv.scipro.forum.dataobjects.ProjectThread; +import se.su.dsv.scipro.forum.dataobjects.QProjectThread; +import se.su.dsv.scipro.project.Project; +import se.su.dsv.scipro.system.GenericRepo; import java.util.List; @@ -23,26 +20,4 @@ public class ProjectThreadRepositoryImpl extends GenericRepo<ProjectThread, Long public List<ProjectThread> findByProject(Project project) { return findAll(QProjectThread.projectThread.project.eq(project)); } - - @Override - public long getUnreadThreadsCount(Project project, User user) { - StringBuilder sql = new StringBuilder() - .append("select count(distinct(thread_id)) result ") - .append(" from (select fp.thread_id as thread_id, fp.id as post_id, ") - .append(" exists (select `read` ") - .append(" from forum_post_read_state fprs ") - .append(" where fprs.forum_post_id = fp.id and ") - .append(" fprs.user_id = :uid and ") - .append(" fprs.read = 1) as post_read ") - .append(" from project_thread pt, forum_post fp ") - .append(" where pt.thread_id = fp.thread_id and ") - .append(" pt.project_id = :pid) tbl_ex ") - .append(" where post_read = 0"); - Query query = em().createNativeQuery(sql.toString()); - query.setParameter("uid", user.getId()) - .setParameter("pid", project.getId()); - - return (Long)query.getSingleResult(); - } - }