专栏首页飞天小牛肉Echo 的发布评论是怎么做的

Echo 的发布评论是怎么做的

先梳理下发布评论这个逻辑需要做哪些事情:

  • 步骤 1:增加评论数据(向评论表 comment 中添加记录行)
  • 步骤 2:修改帖子的评论数量(帖子表 discuss_post 中内置了 comment_count 字段)

这样,处理发布评论这个逻辑的 Service 层方法就需要执行两次 DML 操作,所谓 DML 就是数据操纵语言, 属于 SQL 语言四大分类(数据查询语言 DQL、数据操纵语言 DML、数据定义语言 DDL、数据控制语言 DCL)中的其中一个,简单来说,对数据库进行添加 insert、修改 update 和删除 delete 操作的就是 DML 操作。

那么,如果步骤 1 执行成功了,而步骤 2 执行失败了,就相当于评论添加成功了但是帖子的评论数量没有修改;如果步骤 1 执行失败而步骤 2 执行成功了,就相当于帖子的评论数量增加了但是评论却没有被添加进来。

因此,我们需要保证这两个步骤要么全部成功,要么全部失败。

也就是说我们需要保证原子性。为此,在发布评论这块,我们需要引入事务管理

前置知识:Spring 事务管理

Spring 中支持两种方式事务管理:

1)基于 TransactionTemplate 的编程式事务,实际中很少使用

2)基于 xml 配置或者注解 @Transactional 的声明式事务。

声明式事务管理实际是通过 AOP 实现的,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

显然声明式事务管理要优于编程式事务管理,这正是 Spring 倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,只要简单的在方法上加上 @Transactional 注解就可以获得完全的事务支持。

不过,和编程式事务相比,声明式事务确实存在一些不足,后者的最细粒度只能作用到方法级别。

当然,对于我们发布评论这个逻辑来说,作用到方法级别已经足够了。

另外,我们还可以通过 @Transactional 注解的 isolation 参数配置隔离级别、以及通过 propagation 参数配置传播行为

示例用法如下:

@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)

隔离级别主要定义了如下 5 种:

public enum Isolation {
    DEFAULT(-1),
    READ_UNCOMMITTED(1),
    READ_COMMITTED(2),
    REPEATABLE_READ(4),
    SERIALIZABLE(8);

后面四种就不多说,耳熟能详,读取未提交、读取已提交、可重复读以及可序列化。

第一个 DEFAULT 表示使用底层数据库的默认隔离级别。比如我在 Echo 这个项目中使用的数据库是 MySQL,引擎是 InnoDB,其默认隔离级别就是可重复读 REPEATABLE_READ

传播行为主要有 7 种,意思就是说如果在开始当前事务之前,一个事务上下文已经存在了,那么你有这 7 种选择可以指定当前事务接下来的执行行为:

public enum Propagation {
    REQUIRED(0),
    SUPPORTS(1),
    MANDATORY(2),
    REQUIRES_NEW(3),
    NOT_SUPPORTED(4),
    NEVER(5),
    NESTED(6);
  • REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  • SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
  • MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
  • REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
  • NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  • NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
  • NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于REQUIRED

Service 层

CommentService,就是这个方法执行了两次 DML,需要使用事务管理。

表现层

以下代码在 CommentController 中,只截取了一部分,其他无关代码我就没截了:

逻辑很简单,为这条评论赋值(发布人的 Id,评论的状态,发布时间)然后调用 Service 层方法,有些小白同学可能会纳闷,还有评论的内容 comment、评论针对的实体类型 entityType、实体 ID entityId、以及这条评论是针对哪个用户的(targetId),这些字段在哪里赋值了呢?

是这样的,SpringMVC 可以自动将 JSON 数据转化为 Java 对象,所以,在使用 form 表单进行提交的时候,如果前端页面的属性名(name)和实体类(Comment 类)的属性名一致,那么后端就可以直接使用实体类作为参数接收前端传值。

下面是发布对帖子(在 CommunityConstant 中定义了其实体类型为 1)的评论的部分前端代码:

下面是发布对评论(在 CommunityConstant 中定义了其实体类型为 2)的回复的部分前端代码:

  • 博主小硕在读,深耕 Java,目前在维护一个教程类仓库 CS-Wiki「Gitee 官方推荐项目,现已 1.6k+ star,仓库地址:https://gitee.com/veal98/CS-Wiki」,公众号上的文章也会在此同步更新,欢迎各位前来交流学习。
  • 准备春招秋招的小伙伴可以参考我的这个论坛项目 Echo「Gitee 官方推荐项目,现已 700+ star,仓库地址:https://gitee.com/veal98/Echo」。配套教程正在同步更新中,公众号后台回复 "Echo" 即可免费获取。
  • 另外,虽然现在本号仍然很小,不过我还是建了一个交流群『小牛肉和它的小伙伴们』,感兴趣的各位可以下方扫码加我微信回复 "进群",我拉你进群:

本文分享自微信公众号 - 飞天小牛肉(CS-Wiki),作者:飞天小牛肉

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-05-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Echo 的发送私信是怎么做的

    这篇教程新鲜的东西不多,私信发送和帖子发布的做法如出一辙,都是使用 Ajax 异步实现,参见这篇文章:Echo 的发帖操作是怎么做的

    飞天小牛肉
  • Echo 的发帖操作是怎么做的

    最常用最原始的,form 表单。通过 form 表单以 post/get 方式提交数据,当你点击 submit 按钮时,浏览器会把你在 input 里面输入的数...

    飞天小牛肉
  • Echo 的点赞模块是怎么做的

    需要特别注意的是,Redis key 命名需具有简洁性、可读性以及可管理性,根据阿里云的 Redis 开发规范,我们给 Redis key 起名的时候需要遵守这...

    飞天小牛肉
  • Echo 的关注模块是怎么做的

    关注的目标可以是用户、帖子等,在实现时将这些目标抽象为实体就行了,目前为止 Echo 中只实现了关注用户功能。

    飞天小牛肉
  • Echo 的注册功能是怎么做的

    另外,默认未激活的用户状态 status=0 也会存入数据库,当然,我们会为该注册用户随机生成一个唯一的激活码一并存入数据库:

    飞天小牛肉
  • Echo 的系统通知模块是怎么做的

    系统通知是一个很常见且必要的需求,当发生点赞、关注、评论操作的时候,系统就会给相应的用户发送通知。

    飞天小牛肉
  • Echo 的评论是如何显示的

    关于评论模块需要注意的就是评论表 comment 的设计,这个表应该是相对来说最复杂的一张了。因为不仅有评论(对帖子的评论),还有对评论的回复,都放在这一张表里...

    飞天小牛肉
  • Echo 的帖子列表与分页是怎么做的

    业务逻辑这个模块的文章后续应该都会改成一元钱的付费文章了,emmm,算是一点精神上的慰藉吧。毕竟这种类型的文章不像 Java 八股文那样铺天盖地都是现成的博客、...

    飞天小牛肉
  • Echo 的登录认证和授权是怎么做的

    首先,登录的时候会随机生成验证码,如何把这个验证码和当前用户对应起来,实现验证码的校验呢?

    飞天小牛肉
  • Echo 的私信列表与详情页是怎么做的

    需要注意的是:这张表不仅存储用户之间的私信,也存储系统通知,不同的是,系统通知的 from_id 特定为 1,而这个 id 为 1 的用户是我们手动内置进去的。

    飞天小牛肉
  • Deno TCP Echo Server 是怎么运行的

    在 “了不起的 Deno 入门教程” 这篇文章中,我们介绍了如何使用 Deno 搭建一个简单的 TCP echo server,本文将使用该示例来探究 TCP ...

    山月
  • 淘宝的评论归纳是用什么方法做到的?

    文章目录 1. 识别、抽取产品特征 2. 特征语意去重 3. 识别产品特征对应的观点词 4. 分析评论的情感及强度 5. 后记 越来越多的人选择在网上消费,...

    机器学习AI算法工程
  • Tensorflow的LRN是怎么做的

    LRN全称是local response normalization,局部响应归一化,想了解原理的点这个AlexNet(http://papers.nips.c...

    用户1332428
  • Vue 3.2 发布了,那尤雨溪是怎么发布 Vue.js 的?

    之前写的《学习源码整体架构系列》 包含jQuery、underscore、lodash、vuex、sentry、axios、redux、koa、vue-devt...

    若川
  • 我是怎么把研发安全做“没”了的

    我叫王大锤,万万没想到,我成了马栏山不省心集团的研发安全工程师……这一定是对我的终极考验,相信用不了多久我就会升职加薪,当上总经理,出任CEO,迎娶白富美,走向...

    FB客服
  • 我们是怎么做Code Review的

    前几天看了《Code Review 程序员的寄望与哀伤》,想到我们团队开展Code Review也有2年了,结果还算比较满意,有些经验应该可以和大家一起分享、探...

    李海彬
  • 亚马逊发布智能时尚助手Echo Look,引发大量吐槽

    安妮 李林 编译整理 量子位 出品 | 公众号 QbitAI 昨天,亚马逊推出了一款名叫Echo Look的新设备。它在Alexa、Echo基础之上添加了拍照与...

    量子位
  • 开发知识 | 即时通讯是怎么做到的?

    即时通讯(Instant Messenger,简称IM)软件多是基于TCP/IP和UDP进行通讯的,TCP/IP和UDP都是建立在更低层的IP协议上的两种通讯传...

    APICloud官方
  • kubernetes是怎么做资源管理的?

    在Kubernetes中,Pod是最小的调度单元,所以跟资源和调度相关的属性都是Pod对象的字段,而其中最重要的就是CPU和内存。如下所示:

    极客运维圈

扫码关注云+社区

领取腾讯云代金券