java点赞功能实现_JavaWeb中点赞功能的实现及完整实例

实现原理

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/573722.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数学作图工具_科研论文作图系列-从PPT到AI (一)

导语:之前的推送中,小编给大家介绍过几款科研作图软件,包括统计分析软件Origin和Prism,图像处理软件ImageJ等等。从本期开始,小编将和大家一起继续学习科研论文作图。重点介绍图像的处理和排版,用到的工具主…

传送图片程序

前言:以C#为程序设计基础,传输大图片,并现实。在过程中,采用套接字,单线程同步机制为例子。需要深化,可以采用异步或者多线程的机制,保障能够顺利执行。具体代码可以到微云下载【链接&#xff1…

java中no1_【Java】-- 网络编程のNo.1

在现有的网络中,网络通讯的方式主要有两种:TCP(传输控制协议)方式UDP(用户数据报协议)方式在网络通讯中,TCP方式就类似于拨打电话,使用该种方式进行网络通讯时,需要建立专门的虚拟连接,然后进行可靠的数据传…

优启通怎么重装系统win10_重装系统失败?小编教你安全给神舟战神GX9 Pro重装win10系统方法...

神舟战神GX9 Pro 上市于2016年1月,虽然现在已经停产,但是还是有不少用户依旧十分喜爱这款笔记本。这款笔记本的性能完全对得起它的售价,很多用户都反馈其比外星人电脑要好。对于爱玩游戏的用户而言,对它17.3英寸的显示屏简直欲罢不…

.NET小细节

1、equals()和运算符的区别 C#中有两种不同的相等:引用相等和值相等。值相等是两个对象包含相同的值;引用相等是两个对象引用的是同一个对象。 “”操作符比较的是两个变量的值是否相等,或两个引用是不是指向同一个内存地址(类似比…

java exception用法_Java基础回顾_Exception异常使用详解

package 内部类异常包装器;public class 异常 {/*** 1.异常:* 有Error和Exception两个基本子类* 2.Error:* Error表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。* 3.Exception:* 表示一种设计或实现问题。也就是说&…

获得代理ippython_Python搭建代理IP池实现获取IP的方法

使用爬虫时,大部分网站都有一定的反爬措施,有些网站会限制每个 IP 的访问速度或访问次数,超出了它的限制你的 IP 就会被封掉。对于访问速度的处理比较简单,只要间隔一段时间爬取一次就行了,避免频繁访问;而…

20135202闫佳歆--week 8 实验:理解进程调度时机跟踪分析进程调度与进程切换的过程--实验及总结...

week 8 实验:理解进程调度时机跟踪分析进程调度与进程切换的过程 1.环境搭建: rm menu -rf git clone https://github.com/megnning/menu.git cd menu ls make rootfs qemu -kernel ../linux-3.18.6/arch/x86/boot/bzImage -initrd ../rootfs.img -s -S …

java jni技术_JNI技术简介

JNI(Java Native Interface)提供一种Java字节码调用C/C的解决方案,JNI描述的是一种技术。NDK(Native Development Kit)Android NDK 是一组允许您将 C 或 C(“原生代码”)嵌入到 Android 应用中的工具,NDK描述的是工具集。 能够在 Android 应用中使用原生…

python 读取mysql大量数据处理_python使用多线程快速把大量mysql数据导入elasticsearch...

使用python多线程,运行时自定义线程数,自动计算每个线程处理的数据量,连接mysql读取数据,处理成需要的字段入到elasticsearch。运行效果图:10个线程 运行会在这里实时刷新,方便查看每个线程处理到的id数&am…

java web redis_java web redis使用(二)

上篇中已经安装好redis,然后下面就说怎么在java web中用客户端来使用regis使用jedis java客户端一:一个简单的示例代码:public static void main(String[] args) {Jedis jedis new Jedis( "147.151.240.234" , 6379 );jedis.set("foo&…

mysql 主从_搭建mysql主从并编写监控主从状态脚本

要求:两台centos7虚拟机分为主和从安装mysqlyum -y install mysql mysql-server关闭防火墙service iptables stopsetenforce 0上面的主从都做。修改主的配置文件vi /etc/my.cnf#添加server-id1log-binmysqlbinrelay-logrelays之后保存退出重启mysql服务service …

Ubuntu Sublime Text 3 搜狗拼音

已知前置条件 本经验目前在Ubuntu14.04环境下&#xff0c;已有搜狗输入法 for Linux和Sublime Text 3的情况下安装成功。 解决方法步骤 保存下面的代码到文件sublime_imfix.c(位于~目录) #include <gtk/gtkimcontext.h> void gtk_im_context_set_client_window (GtkIMCon…

Java核心技术点之动态代理

本篇博文会从代理的概念出发&#xff0c;介绍Java中动态代理技术的使用&#xff0c;并进一步探索它的实现原理。由于个人水平有限&#xff0c;叙述中难免出现不清晰或是不准确的地方&#xff0c;希望大家可以指正&#xff0c;谢谢大家&#xff1a;&#xff09; 一、概述 1. 什么…

pythonwebview自动化测试_GitHub - githubwzg/python-appium: 基于PageObject UI自动化测试框架,支持Android/iOS...

0910 UPDATE新增控件集参数化&#xff0c;相同测试步骤的Android/iOS可共用一份测试用例不同测试步骤的用例还需要单独写0904 UPDATE优化Android log及crsahinfo相关输出路径新增iOS crashreport解析新增内容&#xff1a;适配iOS提取android crash信息优化report(增加自动填充包…

linux中使用lftp上传下载文件

lftp是linux中一款ftp服务器相比windows中的ftp显得要复杂不少了&#xff0c;下面我来总结一下lftp文件上传&#xff0c;文件下载&#xff0c;及文件查找等等相关命令吧。 lftp连接的几种方法&#xff0c;最常用的是lftp namesite&#xff0c;这样可以不用明文输入密码。 1、lf…

java 数据库 事务 只读_不使用事务和使用只读事务的区别

转转转&#xff0c;&#xff0c;还需要具体验证(决定把readonly类型的事务完全去掉&#xff0c;以提高性能&#xff0c;这里有讨论&#xff1a;http://stackoverflow.com/questions/2562865/spring-transaction-readonly)。。。如果只提交一个查询&#xff0c;有必要用事务吗&a…

python搭建webapi_怎么搭建Web Api

1.通常我们有个web 让后可以有个web api 提供接口2.通常我们分别建两个项目 web api 依赖web的来进行访问(说到底是依赖是IIS)3.我们先建个SmallCode.Test.Web 再建一个SmallCode.Test.Api4.直接在SmallCode.Test.Web 引用 SamllCode.Test.Api 运行通过地址 /api/Order 无法访问…

shell入门之expr的使用

在expr中加减乘除的使用&#xff0c;脚本例如以下&#xff1a; #!/bin/sh #a test about expr v1expr 5 6 echo "$v1" echo expr 3 5 echo expr 6 / 2 echo expr 9 \* 5 echo expr 9 - 6 执行效果 转载于:https://www.cnblogs.com/bhlsheji/p/5401458.html

java中子线程与主线程通信_Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息...

之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息&#xff0c;然后在主线程(UI线程)中获取消息并修改UI&#xff0c;那么可以不可以在由主线程发送消息&#xff0c;子线程接收呢&#xff1f;我们按照之前的思路写一下代码&#xff1a;packagecn.lixyz.handlertest;…