网站首页 > 精选文章 / 正文
废话不多说直接上步骤,首先涉及到的就是需要操作的两个实体类对象一个是帖子实体、一个是用户点赞实体,这也是点赞功能的一个数据库模型。假设我们有一个Post(帖子)实体,包含了每个Post记录点赞数。然后Like实体来存储用户对每个帖子点赞的记录,以便避免用户重复点赞。如下所示。
实体类定义
Post实体
记录帖子内容和点赞数量。
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String content;
private int likeCount;
// getters and setters
}
Like实体
存储用户对某个帖子是否点赞。每条记录对应一个用户和一个帖子。
@Entity
public class Like {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "post_id", nullable = false)
private Post post;
@ManyToOne
@JoinColumn(name = "user_id", nullable = false)
private User user;
// getters and setters
}
创建Repository
为Post和Like创建Repository,用于数据库操作,如下所示。
@Repository
public interface PostRepository extends JpaRepository<Post, Long> {
}
@Repository
public interface LikeRepository extends JpaRepository<Like, Long> {
Optional<Like> findByUserAndPost(User user, Post post);
int countByPost(Post post);
}
其中,findByUserAndPost方法用于查找某个用户对某个帖子的点赞记录,以便判断是否已点赞。countByPost方法用于统计某个帖子的点赞数。
编写Service 层
接下就是在业务逻辑Service层中实现相关的点赞逻辑,例如判断是否已点赞、增加点赞记录等。
@Service
public class LikeService {
@Autowired
private PostRepository postRepository;
@Autowired
private LikeRepository likeRepository;
public void likePost(Long postId, User user) {
Post post = postRepository.findById(postId)
.orElseThrow(() -> new RuntimeException("Post not found"));
// 检查用户是否已对该帖子点赞
if (likeRepository.findByUserAndPost(user, post).isPresent()) {
throw new RuntimeException("You have already liked this post");
}
// 创建新的点赞记录
Like like = new Like();
like.setPost(post);
like.setUser(user);
likeRepository.save(like);
// 更新帖子点赞数
post.setLikeCount(likeRepository.countByPost(post));
postRepository.save(post);
}
public void unlikePost(Long postId, User user) {
Post post = postRepository.findById(postId)
.orElseThrow(() -> new RuntimeException("Post not found"));
Like like = likeRepository.findByUserAndPost(user, post)
.orElseThrow(() -> new RuntimeException("You haven't liked this post"));
// 删除点赞记录
likeRepository.delete(like);
// 更新帖子点赞数
post.setLikeCount(likeRepository.countByPost(post));
postRepository.save(post);
}
}
介绍一下两个核心方法的作用,
- likePost方法:其主要的作用就是用于点赞,在方法中首先检查用户是否已点赞,如果没有点赞,则添加一条新的点赞记录,并更新帖子的点赞数。
- unlikePost方法:主要是用于取消点赞,在方法中首先检查用户是否已点赞,如果已经点赞,如果点赞了则删除记录,并更新帖子的点赞数。
编写Controller层
在Controller层中调用Service层的方法来实现用户点赞了取消点赞的功能。
@RestController
@RequestMapping("/posts")
public class PostController {
@Autowired
private LikeService likeService;
@PostMapping("/{postId}/like")
public ResponseEntity<String> likePost(@PathVariable Long postId, @AuthenticationPrincipal User user) {
likeService.likePost(postId, user);
return ResponseEntity.ok("Liked post successfully");
}
@PostMapping("/{postId}/unlike")
public ResponseEntity<String> unlikePost(@PathVariable Long postId, @AuthenticationPrincipal User user) {
likeService.unlikePost(postId, user);
return ResponseEntity.ok("Unliked post successfully");
}
}
获取帖子详情的时候,将点赞数量反馈到前端进行展示。
@GetMapping("/{postId}")
public ResponseEntity<Post> getPost(@PathVariable Long postId) {
Post post = postRepository.findById(postId)
.orElseThrow(() -> new RuntimeException("Post not found"));
return ResponseEntity.ok(post);
}
处理并发问题
在高并发场景下,可能会出现多个用户重复点赞的功能,这种情况我们一般采用的方式是通过数据库唯一性约束 或 分布式锁 来处理,如下所示。
使用数据库唯一性约束
在数据库中为Like表添加一个唯一约束,确保user_id和post_id的组合唯一,如果用户重复点赞,数据库会抛出唯一性约束异常。我们可以捕获这个异常并返回一个适当的提示信息。
使用分布式锁
在高并发场景中,一般可以通过Redis来实现分布式锁来防止并发安全问题。通过Redisson库实现对likePost方法的分布式锁控制,防止同一个用户多次点赞。
总结
通过上面的方式,我们就可以实现一个简单的点赞功能,在前端我们通过Ajax请求来分别发送点赞了取消点赞的请求。来及时的处理页面对于点赞数量的更新操作。我们也可以更具实际情况对相关的业务逻辑进行升级优化来保证系统的高效稳定。
Tags:manytoone
猜你喜欢
- 2024-12-17 最经典的Spring Boot快速入门视频教程
- 2024-12-17 Spring Boot JPA:简单高效的数据库操作利器
- 2024-12-17 4 个Spring Data JPA性能提升技巧,让你的程序更丝滑!
- 2024-12-17 浪漫中英文赠言:照亮你的心灵、生活和世界
- 2024-12-17 皮克斯电影中隐藏的这些小细节 你注意到了吗?
- 2024-12-17 Java 如何将 List 转换为 MAP java list转map的三种方法
- 2024-12-17 年轻的时候,如果不做点疯狂的事,当你老了,怎么吹牛啊?
- 2024-12-17 起底many,much和a lot of的关系,撸清了关系,句子随意切换
- 2024-12-17 盘点:世界各国千奇百怪的迎新年风俗