Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【SpringBoot】论坛项目中如何进行实现发布文章,以及更新对应数据库的数据更新

【SpringBoot】论坛项目中如何进行实现发布文章,以及更新对应数据库的数据更新

作者头像
用户11288949
发布于 2025-02-28 01:25:57
发布于 2025-02-28 01:25:57
9300
代码可运行
举报
文章被收录于专栏:学习学习
运行总次数:0
代码可运行

📚️1.数据库设计

🚀1.1数据库

小编使用的是navicat,具体的数据库如下所示,由于发表文章设计三个数据库:

文章数据库,板块数据库,作者数据库(这里指的就是用户数据库)

文章数据库:

包含了文章id,文章属于那个板块,所以板块id,谁发表的就是用户id,以及文章题目,内容,以及点赞数,回复数,浏览量等等,可以看看表的英文解释;

用户数据库:

这里就包含了用户id(与文章里的对应),以及username,password,包含比较重要的一些用户数据;

板块数据库:

这里就是每个板块的信息,板块名字,板块内发布的文章的数量,先后顺序等等.....

🚀1.2板块数据库SQL语句编写

分析:

我们要发布一篇文章,那么发布文章后,对应发布文章的作者对应的发布数量要增加,以及文章属于那个板块,那么板块包含的数量也要增加,所以这里涉及到三个数据库的操作;

1.2.1用户表更新数据

这里很明显是动态更新,具体的SQL语句如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<update id="updateByPrimaryKeySelective" parameterType="com.example.forum.model.User">
    update t_user
    <set>
      <if test="username != null">
        username = #{username,jdbcType=VARCHAR},
      </if>
      <if test="password != null">
        password = #{password,jdbcType=VARCHAR},
      </if>
      <if test="nickname != null">
        nickname = #{nickname,jdbcType=VARCHAR},
      </if>
      <if test="phoneNum != null">
        phoneNum = #{phoneNum,jdbcType=VARCHAR},
      </if>
      <if test="email != null">
        email = #{email,jdbcType=VARCHAR},
      </if>
      <if test="gender != null">
        gender = #{gender,jdbcType=TINYINT},
      </if>
      <if test="salt != null">
        salt = #{salt,jdbcType=VARCHAR},
      </if>
      <if test="avatarUrl != null">
        avatarUrl = #{avatarUrl,jdbcType=VARCHAR},
      </if>
      <if test="articleCount != null">
        articleCount = #{articleCount,jdbcType=INTEGER},
      </if>
      <if test="isAdmin != null">
        isAdmin = #{isAdmin,jdbcType=TINYINT},
      </if>
      <if test="remark != null">
        remark = #{remark,jdbcType=VARCHAR},
      </if>
      <if test="state != null">
        state = #{state,jdbcType=TINYINT},
      </if>
      <if test="deleteState != null">
        deleteState = #{deleteState,jdbcType=TINYINT},
      </if>
      <if test="createTime != null">
        createTime = #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="updateTime != null">
        updateTime = #{updateTime,jdbcType=TIMESTAMP},
      </if>
    </set>
    where id = #{id,jdbcType=BIGINT}
  </update>
1.2.2板块表更新数据

很明显这里肯定也是动态更新的过程:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 <update id="updateByPrimaryKeySelective" parameterType="com.example.forum.model.Board">
    update t_board
    <set>
      <if test="name != null">
        name = #{name,jdbcType=VARCHAR},
      </if>
      <if test="articleCount != null">
        articleCount = #{articleCount,jdbcType=INTEGER},
      </if>
      <if test="sort != null">
        sort = #{sort,jdbcType=INTEGER},
      </if>
      <if test="state != null">
        state = #{state,jdbcType=TINYINT},
      </if>
      <if test="deleteState != null">
        deleteState = #{deleteState,jdbcType=TINYINT},
      </if>
      <if test="createTime != null">
        createTime = #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="updateTime != null">
        updateTime = #{updateTime,jdbcType=TIMESTAMP},
      </if>
    </set>
    where id = #{id,jdbcType=BIGINT}
  </update>
1.2.3文章表发布数据

这里发布,那么就是往数据库中插入数据:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<insert id="insertSelective" parameterType="com.example.forum.model.Article">
    insert into t_article
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="boardId != null">
        boardId,
      </if>
      <if test="userId != null">
        userId,
      </if>
      <if test="title != null">
        title,
      </if>
      <if test="visitCount != null">
        visitCount,
      </if>
      <if test="replyCount != null">
        replyCount,
      </if>
      <if test="likeCount != null">
        likeCount,
      </if>
      <if test="state != null">
        state,
      </if>
      <if test="deleteState != null">
        deleteState,
      </if>
      <if test="createTime != null">
        createTime,
      </if>
      <if test="updateTime != null">
        updateTime,
      </if>
      <if test="content != null">
        content,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=BIGINT},
      </if>
      <if test="boardId != null">
        #{boardId,jdbcType=BIGINT},
      </if>
      <if test="userId != null">
        #{userId,jdbcType=BIGINT},
      </if>
      <if test="title != null">
        #{title,jdbcType=VARCHAR},
      </if>
      <if test="visitCount != null">
        #{visitCount,jdbcType=INTEGER},
      </if>
      <if test="replyCount != null">
        #{replyCount,jdbcType=INTEGER},
      </if>
      <if test="likeCount != null">
        #{likeCount,jdbcType=INTEGER},
      </if>
      <if test="state != null">
        #{state,jdbcType=TINYINT},
      </if>
      <if test="deleteState != null">
        #{deleteState,jdbcType=TINYINT},
      </if>
      <if test="createTime != null">
        #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="updateTime != null">
        #{updateTime,jdbcType=TIMESTAMP},
      </if>
      <if test="content != null">
        #{content,jdbcType=LONGVARCHAR},
      </if>
    </trim>
  </insert>

📚️2.Dao层的设计

这里很简单就是设计接口与数据库进行连接,种类小编将三种接口的设计一起写入到下方:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//板块数据的动态更新
int updateByPrimaryKeySelective(Board record);

//用户数据的动态更新
 int updateByPrimaryKeySelective(User record);

//文章的发布(插入)
int insertSelective(Article record);

注意:每个方法的名字要和上述SQL在xml中的id要保持一致,不然会出现无法找到我们所需要的SQL语句来操作数据库;

📚️3.Service层的设计

🚀3.1用户service层

这里先规定service接口,在使用实现类进行实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  /**
     * 用户发布帖子后进行帖子数量的增加
     * @param id
     */
    void addOneArticleCountById(Long id);

对应的实现类的代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
    public void addOneArticleCountById(Long id) {
        //校验参数
        if(id == null || id <= 0){
            log.warn(ResultCode.FAILED_BOARD_ARTICLE_COUNT.toString());
            throw new ApplicationException(AppResult.fail(ResultCode.FAILED_BOARD_ARTICLE_COUNT));
        }

        //进行获取对象
        User user = userMapper.selectByPrimaryKey(id);

        //校验这里的对象是否存在
        if(user == null){
            log.warn(ResultCode.ERROR_IS_NULL.toString() + ", user id = " + id);
            // 抛出异常
            throw new ApplicationException(AppResult.fail(ResultCode.ERROR_IS_NULL));
        }

        //然后通过更新这里的文章数量
        User updataUser = new User();
        updataUser.setId(user.getId());
        updataUser.setArticleCount(user.getArticleCount() + 1);

        //更新
        int result = userMapper.updateByPrimaryKeySelective(updataUser);
        if(result != 1){
            log.warn(ResultCode.FAILED.toString());
            throw new ApplicationException(AppResult.fail(ResultCode.FAILED));
        }
    }

大体的步骤就是:对于id进行参数的校验,然后通过id拿到这里的用户的对象;再次进行非空的校验,最后就是设修改的对象,传入用户要修改的信息即可;那么最后一步就是判断这里的修改行数是否是1即可;

🚀3.2板块service层

大致和用户差不多,service实现类如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 @Override
    public void addOneArticleCountById(Long id) {
        //首先判断id参数的合法性
        if(id == null || id <= 0){
            log.warn("没有找到对应的板块,id:" + id);
            throw new ApplicationException(AppResult.fail(ResultCode.FAILED_BOARD_ARTICLE_COUNT));
        }
        //根据id查询对应的板块
        Board board = boardMapper.selectByPrimaryKey(id);
        //校验是否正确
        if(board == null){
            //此时板块为空
            log.warn(ResultCode.ERROR_IS_NULL.toString());
            throw new ApplicationException(AppResult.fail(ResultCode.ERROR_IS_NULL));
        }

        //更新这里的文章的数量
        Board updataBoard = new Board();
        updataBoard.setId(board.getId());
        updataBoard.setArticleCount(board.getArticleCount() + 1);

        int result = boardMapper.updateByPrimaryKeySelective(updataBoard);

        //判断这里的更新是否出现了的错误
        if(result != 1){
            log.warn(ResultCode.FAILED.toString());
            throw new ApplicationException(AppResult.fail(ResultCode.FAILED));
        }
    }

和用户板块差不多,那么这里抛出异常主要是为了事务进行准备;

🚀3.3文章service层

在接口中由于这里涉及三个表的设计,所以为了保证安全性,这里使用事务,保证三个数据库更改一起成功或者一起失败:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  @Transactional
    void create(Article article);

那么至于service层代码来说:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 public void create(Article article) {
        //进行参数的校验
        if(article == null || article.getUserId() == null
        || article.getBoardId() == null
        || !StringUtils.hasLength(article.getContent())
        || !StringUtils.hasLength(article.getTitle())){
            log.warn(ResultCode.FAILED_PARAMS_VALIDATE.toString());
            throw new ApplicationException(AppResult.fail(ResultCode.FAILED_PARAMS_VALIDATE));
        }

        //设置默认值
        article.setVisitCount(0); // 访问数
        article.setReplyCount(0); // 回复数
        article.setLikeCount(0); // 点赞数
        article.setDeleteState((byte) 0);
        article.setState((byte) 0);
        Date date = new Date();
        article.setCreateTime(date);
        article.setUpdateTime(date);

        //进行创建文章的操作
        int result = articleMapper.insertSelective(article);
        if(result != 1){
            throw new ApplicationException(AppResult.fail(ResultCode.FAILED_CREATE));
        }

        //更新这里的用户表数据以及板块表数据
        //这里要进行校验的操作,利用事务进行轮滚或者是提交
        User user = userServiceImp.selectById(article.getUserId());
        if(user == null){
            
            throw new ApplicationException(AppResult.fail(ResultCode.FAILED_CREATE));
        }

        userServiceImp.addOneArticleCountById(user.getId());

        Board board = boardServiceImp.selectById(article.getBoardId());
        if(board == null){
          
            throw new ApplicationException(AppResult.fail(ResultCode.FAILED_CREATE));
        }

        boardServiceImp.addOneArticleCountById(board.getId());

    }

大致就是在进行数据校验的判断后,设置要传递的对象实现数据修改,并进行是否成功的判断,然后对于两个板块和用户对象来说,这里还需要进行对应的service层方法的调用实现对应数据库的数据更改;(前提也是进行获得的对象的非空的校验);

这里上述三个service层来说一但抛出异常后,那么事务就会回滚,而不会提交 ,保证了数据的准确性以及正确性;

📚️4.Controller层的设计

这里是发表文章,牵连到三个数据库的设计,所以只需要设计发表文章的控制类即可

具体的代码如下所示:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 @RequestMapping(value = "/create" ,method = RequestMethod.POST)
    public AppResult create(HttpServletRequest request,
                            @RequestParam("boardId") @NonNull Long boardId,
                            @RequestParam("title") @NonNull String title,
                            @RequestParam("content") @NonNull String content){
        //判断用户是否禁言,用户对象从session中进行获取
        HttpSession session = request.getSession(false);

        User user =(User) session.getAttribute(ContentConfig.USER_SESSION);
        if(user.getState() == 1){
            //说明此时用户处于禁言的状态
            return AppResult.fail(ResultCode.FAILED_USER_BANNED);
        }
        //设置传递参数
        Article article = new Article();
        article.setUserId(user.getId());
        article.setBoardId(boardId);
        article.setContent(content);
        article.setTitle(title);

        articleServiceImp.create(article);

        return AppResult.success("发表文章成功");
    }

解释:首先设置路由,以及需要的方法,然后设置的三个参数来说,直接是使用lombok中的NunNull进行非空的校验,然后从session中获取用户对象,设置这里传递的对象,最后调用service层的代码即可;

📚️5.测试

最后我们使用pastman进行测试这里的代码,是否能成功修改我们的数据库:

注意:由于要使用这里的session来获取对象,那么我们首先进行登录,然后再进行测试:

那么此时我们检查一下我们navicat中的数据库:

很明显这里输入的2指的就是板块2,这里的文章数量很明显进行了加一的操作;

然后这里的文章板块也进行了对应的发布操作;

对应的用户发布的文章也进行了加一的操作;

📚️6.总结

本期主要讲解了关于发布文章,牵连的三个数据库表的设计操作,从SQL的编写到Dao层,Service层,Controller层的程序设计;以及最后的结果展示;

🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-02-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
BATJ面试必会之Java IO 篇
实例化一个具有缓存功能的字节流对象时,只需要在 FileInputStream 对象上再套一层 BufferedInputStream 对象即可。
乔戈里
2019/03/10
5880
Java NIO深入理解ServerSocketChannel
JAVA NIO有两种解释:一种叫非阻塞IO(Non-blocking I/O),另一种也叫新的IO(New I/O),其实是同一个概念。它是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,已经被越来越多地应用到大型应用服务器,成为解决高并发与大量连接、I/O处理问题的有效方式。
用户1251985
2019/07/02
1.5K0
Java NIO深入理解ServerSocketChannel
Java面试必问通信框架NIO,原理详解
新的输入/输出 (NIO) 库是在 JDK 1.4 中引入的,弥补了原来的 I/O 的不足,提供了高速的、面向块的 I/O。
李红
2019/05/31
1.3K0
Java面试必问通信框架NIO,原理详解
java——IO与NIO
Java中的IO(输入输出)是用于在程序中读取和写入数据的一种机制。Java提供了两种不同的IO模型:传统的IO模型和NIO(New IO)模型。
一只
2024/07/05
1240
java——IO与NIO
NIO 和 IO 到底有什么区别?别说你不会!
通道是对原 I/O 包中的流的模拟。到任何目的地(或来自任何地方)的所有数据都必须通过一个 Channel 对象(通道)。
Java技术栈
2020/03/17
1.3K0
NIO 和 IO 到底有什么区别?别说你不会!
Java进阶 | IO流核心模块与基本原理
IO技术在JDK中算是极其复杂的模块,其复杂的一个关键原因就是IO操作和系统内核的关联性,另外网络编程,文件管理都依赖IO技术,而且都是编程的难点,想要整体理解IO流,先从Linux操作系统开始。
知了一笑
2021/07/29
3490
NIO
详细知识参考我有道云笔记 package com.shi.nio; import java.nio.ByteBuffer; /** * * @author shiye * 一、缓冲区(Buffer):在 Java NIO 中负责数据的存取。缓冲区就是数组。用于存储不同数据类型的数据 * * 根据数据类型不同(boolean 除外),提供了相应类型的缓冲区: * ByteBuffer * CharBuffer * ShortBuffer * IntBuffer * LongBuf
用户5927264
2019/10/15
7510
【面试题精讲】javaIO模型之NIO
NIO(New I/O)是Java提供的一种非阻塞I/O模型,它在JDK 1.4中引入。与传统的I/O模型相比,NIO提供了更高效、更灵活的I/O操作方式。
程序员朱永胜
2023/10/22
2220
Java IO 与 NIO:高效的输入输出操作探究
输入输出(IO)是任何编程语言中的核心概念,而在Java中,IO操作更是应用程序成功运行的基石。随着计算机系统变得越来越复杂,对IO的要求也日益增加。在本文中,我们将探讨Java IO和非阻塞IO(NIO)的重要性以及如何在Java中实现高效的输入输出操作。
程序那些事
2023/10/17
2590
Java NIO与IO 区别和比较
NIO包(java.nio.*)引入了四个关键的抽象数据类型,它们共同解决传统的I/O类中的一些问题。
IT工作者
2022/03/30
2160
NIO~~
NIO 有三大核心部分:Channel( 通道) ,Buffer( 缓冲区), Selector( 选择器)
大忽悠爱学习
2022/05/06
9150
NIO~~
Java I/O不迷茫,一文为你导航!
学习过计算机相关课程的童鞋应该都知道,I/O 即输入Input/ 输出Output的缩写,最容易让人联想到的就是屏幕这样的输出设备以及键盘鼠标这一类的输入设备,其广义上的定义就是:数据在内部存储器和外部存储器或其他周边设备之间的输入和输出;
我没有三颗心脏
2018/09/14
5410
Java I/O不迷茫,一文为你导航!
java NIO浅析
NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区),Selector(选择器)。传统IO基于字节流和字符流进行操作,而NIO基于Channel和Buffer进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。
Java阿呆
2020/11/04
7080
java NIO浅析
彻底搞懂高性能I/O之道
本文介绍操作系统I/O工作原理,Java I/O设计,基本使用,开源项目中实现高性能I/O常见方法和实现,彻底搞懂高性能I/O之道
用户1260737
2019/11/15
1.2K0
NIO最全教程,看这一篇就够了
Java NIO(New IO 或 Non Blocking IO)是从 Java 1.4 版本开始引入的一个新的 IO API,可以替代标准的 Java IO API。NIO 支持面向缓冲区的、基于通道的 IO 操作。NIO 将以更加高效的方式进行文件的读写操作。
公众号 IT老哥
2020/09/16
6890
NIO最全教程,看这一篇就够了
java的IO模型
本文主要是重新梳理了Java的IO模型,基于之前NIO的文章进行补充,为学习Netty做准备。
贪挽懒月
2020/07/14
7360
Netty系列| Netty创始人告诉你为什么选择NIO
NIO模型 同步非阻塞 NIO有同步阻塞和同步非阻塞两种模式,一般讲的是同步非阻塞,服务器实现模式为一个请求一个线程,但客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
狼王编程
2021/06/01
1.3K0
Netty系列| Netty创始人告诉你为什么选择NIO
NIO详解
NIO (New lO)也有人称之为java non-blocking lO是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的Java lO API。
冬天vs不冷
2025/01/21
1870
NIO详解
Java NIO?看这一篇就够了!
✎前言 现在使用NIO的场景越来越多,很多网上的技术框架或多或少的使用NIO技术,譬如Tomcat,Jetty。学习和掌握NIO技术已经不是一个JAVA攻城狮的加分技能,而是一个必备技能。在前面2篇文
方志朋
2019/06/21
1.1K0
Java NIO?看这一篇就够了!
为什么一个还没毕业的大学生能够把 IO 讲的这么好?
Java IO 是一个庞大的知识体系,很多人学着学着就会学懵了,包括我在内也是如此,所以本文将会从 Java 的 BIO 开始,一步一步深入学习,引出 JDK1.4 之后出现的 NIO 技术,对比 NIO 与 BIO 的区别,然后对 NIO 中重要的三个组成部分进行讲解(缓冲区、通道、选择器),最后实现一个简易的客户端与服务器通信功能。
cxuan
2020/09/14
6140
相关推荐
BATJ面试必会之Java IO 篇
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验