实现原理

1、功能描述:一个用户对同一文章只能点赞一次,第二次就是取消赞

2、建立一个点赞表great,字段有文章ID(aid),点赞用户ID(uid)

3、当有用户进行点赞行为时,使用aid和uid搜索点赞表。

若有该记录,则表示用户已经点过赞,本次点击是取消点赞行为,故删除great表中的该条记录,同时将该文章的点赞数减1。

若无该记录,则表示用户是要点赞,故在great表中添加该记录,同时该文章的点赞数加1。

核心代码分析

核心控制器BaseController:

@Controller

public class BaseController {

private final GreatRepository greatRepository;

private final ArticleRepository articleRepository;

//Spring团队推荐的做法是用构造器来引入依赖,[email protected]

@Autowired

public BaseController(GreatRepository greatRepository,

ArticleRepository articleRepository) {

this.greatRepository = greatRepository;

this.articleRepository=articleRepository;

}

@RequestMapping({"/","/index"})

public String index(){

return "index";

}

//添加事务支持

@Transactional

@RequestMapping("/great")

public String great(@Param("aid") int aid, @Param("uid") int uid, Model model){

//查询是否有该用户对该文章的点赞记录

List list=greatRepository.findByAidAndUid(aid,uid);

if (list!=null && list.size()>0){

//如果找到了这条记录,则删除该记录,同时文章的点赞数减1

Great great=list.get(0);

//删除记录

greatRepository.delete(great.getId());

//文章点赞数减1,查询时使用Mysql行级锁解决并发覆盖问题

Article article=articleRepository.findByIdForUpdate(aid);

article.setGreatNum(article.getGreatNum()-1);

articleRepository.saveAndFlush(article);

}else {

//如果没有找到这条记录,则添加这条记录,同时文章点赞数加1

Great great=new Great();

great.setAid(aid);

great.setUid(uid);

//添加记录

greatRepository.saveAndFlush(great);

//文章点赞数加1,查询时使用Mysql行级锁解决并发覆盖问题

Article article=articleRepository.findByIdForUpdate(aid);

article.setGreatNum(article.getGreatNum()+1);

articleRepository.saveAndFlush(article);

}

model.addAttribute("details",articleRepository.findAll());

return "detail";

}

}

Aritcle实体的持久化仓库ArticleRepository

@Repository

public interface ArticleRepository extends JpaRepository{

@Lock(value = LockModeType.PESSIMISTIC_WRITE)

Article findByIdForUpdate(Integer id);

}

[email protected] [email protected]�锁,在事务中,该行级锁能解决对同一条记录的并发修改问题。

代码中已经附有详细注解

完整实例的相关信息

为了突出重点,项目前端较为简陋,功能已经通过测试。

项目采用的框架:

1、容器框架:SpringBoot

2、持久层框架:Spring Data JPA

3、渲染框架:Thymeleaf

4、版本控制:Git

5、依赖:Maven

6、数据库:Mysql

数据库建表文件Schema.sql:

DROP TABLE IF EXISTS `article`;

/*!40101 SET @saved_cs_client     = @@character_set_client */;

/*!40101 SET character_set_client = utf8 */;

CREATE TABLE `article` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`num` int(11) DEFAULT ‘0‘,

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

/*!40101 SET character_set_client = @saved_cs_client */;

--

-- Dumping data for table `article`

--

LOCK TABLES `article` WRITE;

/*!40000 ALTER TABLE `article` DISABLE KEYS */;

INSERT INTO `article` VALUES (1,1),(2,0);

/*!40000 ALTER TABLE `article` ENABLE KEYS */;

UNLOCK TABLES;

--

-- Table structure for table `great`

--

DROP TABLE IF EXISTS `great`;

/*!40101 SET @saved_cs_client     = @@character_set_client */;

/*!40101 SET character_set_client = utf8 */;

CREATE TABLE `great` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`aid` int(11) NOT NULL,

`uid` int(11) NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

/*!40101 SET character_set_client = @saved_cs_client */;

--

-- Dumping data for table `great`

--

LOCK TABLES `great` WRITE;

/*!40000 ALTER TABLE `great` DISABLE KEYS */;

INSERT INTO `great` VALUES (5,1,1);

/*!40000 ALTER TABLE `great` ENABLE KEYS */;

UNLOCK TABLES;

/*!40103 SET [email protected]_TIME_ZONE */;

特别说明:本文章的目的只是单纯向大家说明点赞这个功能的实现思路。为了保证逻辑尽量清晰和简单,因而并没有涉及到性能优化。示例代码中的锁机制能保证并发访问下的安全性,但会对系统并发性能产生一定的影响,但在一般系统中,由于大量用户同时对同一文章集中点赞的情况并不常见,因此性能损耗扔在可以接受的范围内。

如果大家在使用过程中确实有高并发的需要,那么可以考虑使用Redis这类缓存数据库来替代mysql。Redis是高性能的内存KV数据库,且是单线程运行的,因此性能和安全性问题都能得到完美的解决。

关于JPA中如何使用行级锁,可以参考这篇文章:https://blog.csdn.net/fengyuxue11011/article/details/47039765

原文:https://www.cnblogs.com/snake23/p/11096752.html

java点赞功能实现_JavaWeb中点赞功能的实现及完整实例相关推荐

  1. java 遍历request_java 遍历request中的所有表单数据的实例代码

    java 遍历request中的所有表单数据的实例代码 实例如下: Enumeration rnames=request.getParameterNames(); for (Enumeration e ...

  2. java处理日期的类_Java实现的日期处理类完整实例

    本文实例讲述了java实现的日期处理类.分享给大家供大家参考,具体如下: 开发中常常要使用日期,先小结如下,以备后用. import java.text.ParseException; import ...

  3. php中分页公式,php分页函数完整实例代码

    本文分享一例php分页函数完整实例代码,使用此函数实现分页效果很不错.分享给大家供大家参考. 具体功能代码如下: /* * Created on 2011-07-28 * 使用方法: require_ ...

  4. JAVA打印web页面_JavaWeb实现打印功能

    废话不多说了,直接给大家贴代码了,具体代码如下所示: function printsetup(){ // 打印页面设置 wb.execwb(8,1); } 整理的关于打印的内容 1.控制"纵 ...

  5. java web 获取根目录_javaweb中获取服务器端跟目录方法总结

    先说一下java工程下目录的获取的几种方法,有用的看客可以看一下: 1.new File("relative path").getAbsolutePath(); 2.System. ...

  6. java mime上传_JavaWeb中实现文件上传的方式有哪些?

    上回我们说了下文件下载的方式有哪些,这次我们从不同的环境下简单来说说文件上传的方式有哪些. 文件上传的方式Servlet2.5 方式 Servlet3.0 方式 SpringMVC 方式 案例实操 S ...

  7. java 99乘法表对齐_Java实现九九乘法表的完整实例(对齐版)

    Java实现九九乘法表 思路: 1.看到九九乘法表就可以想到for循环,1-9可以写成一个for循环,自增1 2.那就是双重for循环,第一个for循环用于生成1-9的数值 3.第二个for循环的终止 ...

  8. JavaWeb中点赞功能的实现及完整实例

    实现原理 1.功能描述:一个用户对同一文章只能点赞一次,第二次就是取消赞 2.建立一个点赞表great,字段有文章ID(aid),点赞用户ID(uid) 3.当有用户进行点赞行为时,使用aid和uid ...

  9. java点赞功能的实现,类似微信点赞,用户仅能点赞一次,基于redis进行操作

    1.redis 基本知识 redis5种基本数据 学习参考链接 缓存点赞信息的数据结构是set集合,不太了解的同学请参考上面的链接 2.实现逻辑 传入点赞人id,被点赞的id,以及点赞的状态statu ...

最新文章

  1. SAP 差旅报销集成方案的实现
  2. 本人在学习PHP过程中的随笔心得
  3. Zynq-7000系统公共资源及特性
  4. rxjs里concatMap operators的用法
  5. 震撼世界的基建狂魔,中国制造的超级工程到底有多牛?
  6. 微博关注者数量在计算中的作用
  7. Cortex-M系列处理器指令集区别详解
  8. kudu :impala 和 kuduClient 的选择
  9. (android实战)创建查看试卷答案功能(类似于疯狂小鸟的选关)
  10. AndroidStudio_开发工具_调试功能---Android原生开发工作笔记75
  11. PyTorch——PyTorch也支持通过累加操作实现大的BatchSize的训练
  12. 把python37添加到环境变量配置_linux设置python环境变量 分类: python ...
  13. 应用Canary文件类型阻击勒索软件
  14. 启用zhparser插件时一直报Permission denied
  15. IntelliJ IDEA库存在却报错找不到的解决办法
  16. SAP Enable Now
  17. 记一次联想Y7000P安装黑apple系统地经历
  18. [QT学习]-调色板|选择文件
  19. BT源代码学习心得(五):统一网络服务接口--RawServer -- 转贴自 wolfenstein (NeverSayNever)
  20. 施工现场平面布置及其案例说明

热门文章

  1. MySQL 限制查询结果的记录数
  2. 用python画渐变的圆_使用numpy绘制圆形渐变
  3. 面向对象方法的优势简化软件开发的过程_软件开发技巧的途径
  4. 没有bug队——加贝——Python 45,46
  5. java md2_GitHub - edzjx/Md2Crypto
  6. python 生成字符串_Python字符串生成器,按照特定的顺序
  7. tcp的无延时发送_高并发架构的TCP知识介绍
  8. 数据结构--队列、双端队列实际举例详解(Python代码)
  9. 平行四边形的特殊性质
  10. 037_自动添加防火墙规则,开启某些服务或端口(适用于 RHEL7)