1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package com.tanpu.community.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.tanpu.biz.common.enums.community.CommentTypeEnum;
import com.tanpu.biz.common.enums.community.ReportStatusEnum;
import com.tanpu.common.exception.BizException;
import com.tanpu.common.uuid.UuidGenHelper;
import com.tanpu.community.api.beans.req.theme.ForwardThemeReq;
import com.tanpu.community.api.enums.DeleteTagEnum;
import com.tanpu.community.cache.RedisCache;
import com.tanpu.community.dao.entity.community.CommentEntity;
import com.tanpu.community.dao.entity.community.TimesCountEntity;
import com.tanpu.community.dao.mapper.community.CommentMapper;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static com.tanpu.community.api.constants.RedisKeyConstant.*;
@Service
public class CommentService {
@Resource
private CommentMapper commentMapper;
@Autowired
private UuidGenHelper uuidGenHelper;
@Autowired
private RedisCache redisCache;
@Transactional
public void insertComment(CommentEntity commentEntity) {
commentEntity.setCommentId(uuidGenHelper.getUuidStr());
commentMapper.insert(commentEntity);
//失效缓存
evictThemeCache(commentEntity.getThemeId());
}
public CommentEntity queryByIdIncludeDelete(String commmentId) {
return commentMapper.selectOne(new LambdaQueryWrapper<CommentEntity>()
.eq(CommentEntity::getCommentId, commmentId));
}
//统计主题集合的评论量
public Integer getTotalCountByThemeIds(List<String> themeIds) {
if (CollectionUtils.isEmpty(themeIds)) {
return 0;
}
return commentMapper.selectList((new LambdaQueryWrapper<CommentEntity>()
.in(CommentEntity::getThemeId, themeIds))
.eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED))
.size();
}
//统计主题集合的评论量
public Integer getCommentCountByThemeId(String themeId) {
return commentMapper.selectList((new LambdaQueryWrapper<CommentEntity>()
.eq(CommentEntity::getThemeId, themeId))
.eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED))
.size();
}
//统计主题集合的评论量
public Map<String, Integer> getCountMapByThemeIds(List<String> themeIds) {
if (CollectionUtils.isEmpty(themeIds)){
return new HashMap<>();
}
LambdaQueryWrapper<CommentEntity> wrapper = (new LambdaQueryWrapper<CommentEntity>()
.in(CommentEntity::getThemeId, themeIds))
.eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED)
.groupBy(CommentEntity::getThemeId);
return commentMapper.selectCountByThemeIds(wrapper).stream()
.collect(Collectors.toMap(TimesCountEntity::getId, TimesCountEntity::getTimes));
}
public List<CommentEntity> selectByThemeId(String themeId) {
return redisCache.getList(StringUtils.joinWith("_", CACHE_COMMENT_THEMEID, themeId),
60, () -> {
LambdaQueryWrapper<CommentEntity> queryWrapper = new LambdaQueryWrapper<CommentEntity>()
.eq(CommentEntity::getThemeId, themeId)
.eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED.getCode())
.orderByDesc(CommentEntity::getCreateTime);
return commentMapper.selectList(queryWrapper);
}, new TypeReference<List<CommentEntity>>() {
});
}
public List<CommentEntity> queryCommentsByUserId(String userId, String lastId, Integer pageSize) {
LambdaQueryWrapper<CommentEntity> queryWrapper = new LambdaQueryWrapper<CommentEntity>()
.eq(CommentEntity::getAuthorId, userId)
.eq(CommentEntity::getCommentType, CommentTypeEnum.THEME.getCode())
.eq(CommentEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED.getCode())
.orderByDesc(CommentEntity::getCreateTime);
if (StringUtils.isNotEmpty(lastId)) {
CommentEntity commentEntity = commentMapper.selectOne(new LambdaQueryWrapper<CommentEntity>()
.eq(CommentEntity::getCommentId, lastId));
if (commentEntity == null) throw new BizException("评论未找到,id:" + lastId);
queryWrapper.lt(CommentEntity::getCreateTime, commentEntity.getCreateTime());
}
if (pageSize != null) {
queryWrapper.last("limit " + pageSize);
}
return commentMapper.selectList(queryWrapper);
}
//修改举报状态,可修改已删除
public void updateReportStatus(String commentId) {
CommentEntity commentEntity = queryByIdIncludeDelete(commentId);
if (commentEntity == null) {
throw new BizException("评论未找到,id:" + commentId);
}
commentEntity.setReportStatus(ReportStatusEnum.REPORTED.getCode());
commentMapper.updateById(commentEntity);
//失效缓存
evictThemeCache(commentEntity.getThemeId());
}
//删除评论
@Transactional
public void delete(String commentId, String userId) {
CommentEntity commentEntity = this.queryByIdIncludeDelete(commentId);
if (commentEntity==null || !commentEntity.getAuthorId().equals(userId)){
throw new BizException("删除评论与用户不匹配,commentId:"+commentId+",userId:"+userId);
}
commentEntity.setDeleteTag(DeleteTagEnum.DELETED.getCode());
commentMapper.updateById(commentEntity);
//失效缓存
evictThemeCache(commentEntity.getThemeId());
}
// 失效关联主题缓存
private void evictThemeCache(String themeId){
// 评论内容
redisCache.evict(StringUtils.joinWith("_", CACHE_COMMENT_THEMEID, themeId));
// 主题内容
redisCache.evict(StringUtils.joinWith("_", CACHE_THEME_ID, themeId));
// 评论数
redisCache.evict(StringUtils.joinWith("_", THEME_COMMENT_COUNT, themeId));
}
public List<CommentEntity> queryAll() {
return commentMapper.selectList(new LambdaQueryWrapper<CommentEntity>()
.eq(CommentEntity::getDeleteTag,DeleteTagEnum.NOT_DELETED.getCode())
.orderByAsc(CommentEntity::getCreateTime));
}
public CommentEntity queryByCommentId(String commentId) {
return commentMapper.selectOne(new LambdaQueryWrapper<CommentEntity>().eq(CommentEntity::getCommentId,commentId));
}
public String forwardSyncComment(ForwardThemeReq req, String userId) {
CommentEntity commentEntity = CommentEntity.builder()
.themeId(req.getFormerThemeId())
.authorId(userId)
.content(req.getContent().get(0).getValue())
.commentType(CommentTypeEnum.THEME.getCode())
.build();
this.insertComment(commentEntity);
return commentEntity.getCommentId();
}
}