33.点赞功能

需求:

1.同一个用户只能点赞一次,再次点赞则取消点赞。

2.如果当前用户已经点赞,则点赞按钮高亮显示(前端实现,只需要根据Blog类中的isLike属性表示是否点赞过了)

sql 复制代码
CREATE TABLE `tb_blog` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `shop_id` bigint NOT NULL COMMENT '商户id',
  `user_id` bigint unsigned NOT NULL COMMENT '用户id',
  `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '标题',
  `images` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '探店的照片,最多9张,多张以","隔开',
  `content` varchar(2048) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '探店的文字描述',
  `liked` int unsigned DEFAULT '0' COMMENT '点赞数量',
  `comments` int unsigned DEFAULT NULL COMMENT '评论数量',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=COMPACT;
java 复制代码
package com.xkj.org.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import java.time.LocalDateTime;

/**
 * @author xiankejin
 * @descrition
 * @date 2025/10/25
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_blog")
public class Blog {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    private Long shopId;

    private Long userId;

    private String title;
    /**
     * 探店的照片,最多9张,多张以","隔开'
     */
    private String images;
    /**
     * 探店的文字描述
     */
    private String content;
    /**
     * 点赞数量
     */
    private Integer liked;
    /**
     * 评论数量
     */
    private Integer comments;

    private LocalDateTime createTime;

    private LocalDateTime updateTime;

    /**
     * 用户图标
     */
    @TableField(exist = false)
    private String icon;
    /**
     * 用户姓名
     */
    @TableField(exist = false)
    private String name;


    /**
     * 是否点赞过了
     */
    @TableField(exist = false)
    private Boolean isLike;

}
java 复制代码
@Override
    public List<Blog> queryHotBlog(Integer current) {
        //根据点赞数量倒序排列
        Page<Blog> page = query().orderByDesc("liked")
                .page(new Page<>(current, UserConstant.MAX_PAGE_SIZE));
        List<Blog> records = page.getRecords();
        //这里采用lambda表达式简写
        records.forEach(this::queryBlogUser);
        return records;
    }

    @Override
    public Blog detail(Integer id) {
        Blog blog = getById(id);
        queryBlogUser(blog);
        return blog;
    }

    @Override
    public void likeBlog(Integer id) {
        //1.判断当前用户是否已经点赞
        UserDTO user = UserHolder.getUser();
        //这里的userId一定要转成String类型,因为使用的是StringRedisTemplate
        String key = "blog:liked:" + id.toString();
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, user.getId().toString());
        //如果未点赞,可以点赞
        //这里不要直接判断布尔值,而是使用工具类判断,防止isMember对象为null,报空指针异常
        if (BooleanUtil.isFalse(isMember)) {
            //数据库点赞数 + 1
            boolean isSuccess = update().setSql("liked = liked + 1").eq("id", id).update();
            //数据更新成功了在更新redis
            if (isSuccess) {
                //保存用户id到redis的set集合
                stringRedisTemplate.opsForSet().add(key, user.getId().toString());
            }
        } else {
            //如果点赞,则取消点赞
            //数据库点赞数 - 1
            boolean isSuccess = update().setSql("liked = liked - 1").eq("id", id).update();
            //数据更新成功了在更新redis
            if (isSuccess) {
                //将用户id从redis的set集合中移除
                stringRedisTemplate.opsForSet().remove(key, user.getId().toString());
            }
        }

    }

    /**
     * 给BLog对象添加用户信息
     *
     * @param blog
     */
    private void queryBlogUser(Blog blog) {
        User user = userService.getById(blog.getUserId());
        blog.setName(user.getNickName());
        blog.setIcon(user.getIcon());
        //查询blog是否被点赞
        //1.判断当前用户是否已经点赞
        UserDTO currentUser = UserHolder.getUser();
        String key = "blog:liked:" + blog.getId().toString();
        Boolean isMember = stringRedisTemplate.opsForSet().isMember(key, currentUser.getId().toString());
        blog.setIsLike(BooleanUtil.isTrue(isMember));
    }
相关推荐
向着光芒的女孩20 小时前
【IDEA】关不了的Proxy Authentication弹框探索过程
java·ide·intellij-idea
Filotimo_20 小时前
Spring Boot 整合 JdbcTemplate(持久层)
java·spring boot·后端
李慕婉学姐21 小时前
【开题答辩过程】以《“饭否”食材搭配指南小程序的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·spring·小程序
abments1 天前
pgsql timestamp without time zone > character varying解决方案
java
sanggou1 天前
大数据量查询处理方案 - 内存优化与高效展示
java
没有bug.的程序员1 天前
Java 字节码:看懂 JVM 的“机器语言“
java·jvm·python·spring·微服务
-大头.1 天前
深入理解 Java 内存区域与 JVM 运行机制
java·jvm
没有bug.的程序员1 天前
JVM 整体架构:一套虚拟机的心脏与血管
java·jvm·spring boot·spring cloud·架构
晨枫阳1 天前
不同语言的元组对比
java·前端·javascript
悟能不能悟1 天前
怎么在idea合并2个个branch
java·ide·intellij-idea