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

本文介绍了在JavaWeb中实现点赞功能的逻辑,包括用户只能点赞一次的限制,使用点赞表存储用户行为,并通过Spring Data JPA的行级锁@Lock(LockModeType.PESSIMISTIC_WRITE)解决并发修改问题。示例代码包含控制器、持久化仓库和数据库建表脚本,讨论了性能优化的可能性,如使用Redis应对高并发场景。
摘要由CSDN通过智能技术生成

实现原理

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团队推荐的做法是用构造器来引入依赖,而不是直接使用@Autowired引入

@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);

}

注意其中使用了@Lock注解以及 LockModeType.PESSIMISTIC_WRITE来让JPA使用数据库层的行级锁,在事务中,该行级锁能解决对同一条记录的并发修改问题。

代码中已经附有详细注解

完整实例的相关信息

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

项目采用的框架:

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 TIME_ZONE=@OLD_TIME_ZONE */;

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

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

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

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值