文章管理接口——里面有动态SQL编写,在分页查询里

news2024/11/15 11:52:12

1.实体类和表结构

2. 新增文章分类

接口文档

实现

 

完整代码放在校验部分

结果:

参数校验(Validation自定义)

 

 对state的校验(已发布|草稿),已有的注解不能满足校验需求,这时就需要自定义校验注解

步骤:

  1. 自定义注解State(里面必须提供三个属性message,groups,payload)
  2. 自定义校验数据的类StateValidation实现ConstraintValidator接口(需要重写isValid这个方法,方法内部提供校验规则)
  3. 在需要校验的地方使用自定义注解(Validation会解析到我们自定义的注解@State,解析到了之后就能够找到这个注解,并且解析到这个注解上组合的另外一个注解@Constraint,这个注解的内部会有一个validatedBy的属性,这个属性作用指定谁来提供校验规则,比如validateBy=StateValidation.class,它就指向了我们自定义的StateValidation类,最终调用里面的isValid方法,完成参数的校验)

 新建一个anno软件包,包下新建一个State接口

package org.exampletest.anno;

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import org.exampletest.validation.StateValidation;

import java.lang.annotation.*;

@Documented//元注解,可以抽取到帮助文档里面的

//元注解,标识我们自定义的注解可以用在哪些地方,用在类上还是属性上还是方法上,还是参数上?
// 我们这里只用到属性上
@Target({ElementType.FIELD})

//元注解,标识这个自定义注解将来在哪个阶段会被保留,编译阶段?源码阶段?运行时阶段?
// 我们这里需要保留到运行时阶段
@Retention(RetentionPolicy.RUNTIME)//元注解,标识这个自定义注解将来在哪个阶段会被保留,编译阶段?源码阶段?运行时阶段?我们这里需要保留到运行时阶段

@Constraint(validatedBy = {StateValidation.class})//元注解,标识这个注解的校验逻辑由哪个类实现

public @interface State {
    // 提供校验失败后的提示信息
    String message() default "state参数的值只能时已发布或者草稿";
    //指定分组
    Class<?>[] groups() default {};
    // 负载,获取到state注解的附加信息
    Class<? extends Payload>[] payload() default {};
}

新建一个软件包validation,包下新建一个StateValidation类

package org.exampletest.validation;

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.exampletest.anno.State;

// implements ConstraintValidator<给哪个注解提供校验规则,校验的数据类型>
public class StateValidation implements ConstraintValidator<State,String> {
    /**
     *
     * @param value 将来要校验的数据
     * @param context
     * @return 返回false,校验不通过,返回true校验通过
     */

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        //提供校验规则
        if(value ==null){
            return false;
        }
        if(value.equals("已发布") || value.equals("草稿")){
            return true;
        }
        return false;
    }
}

在Article属性上添加注解:

package org.exampletest.pojo;


import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import org.exampletest.anno.State;
import org.hibernate.validator.constraints.URL;

import java.time.LocalDateTime;
@Data
public class Article {
    private Integer id;//主键ID
    @NotEmpty
    @Pattern(regexp="^\\S{1,10}$")
    private String title;//文章标题
    @NotEmpty
    private String content;//文章内容
    @NotEmpty
    @URL
    private String coverImg;//封面图像
    @State
    private String state;//发布状态 已发布|草稿

    @NotNull
    private Integer categoryId;//文章分类id
    private Integer createUser;//创建人ID
    private LocalDateTime createTime;//创建时间
    private LocalDateTime updateTime;//更新时间
}

service层代码:

package org.exampletest.service;

import org.exampletest.pojo.Article;

public interface ArticleService {

     void add(Article article);
}

service层接口实现:

package org.exampletest.service.impl;

import org.exampletest.mapper.ArticleMapper;
import org.exampletest.pojo.Article;
import org.exampletest.service.ArticleService;
import org.exampletest.utils.ThreadLocalUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.Map;

@Service
public class ArticleServicempl implements ArticleService {

    @Autowired
    private ArticleMapper articleMapper;
    @Override
    public void add(Article article) {
        //补充属性值
        article.setCreateTime(LocalDateTime.now());
        article.setUpdateTime(LocalDateTime.now());

        Map<String,Object> map=ThreadLocalUtil.get();
        Integer userId = (Integer)map.get("id");
        article.setCreateUser(userId);

        articleMapper.add(article);
    }
}

Mapper层: 

package org.exampletest.mapper;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.exampletest.pojo.Article;

@Mapper
public interface ArticleMapper {
    //新增
    @Insert("insert into article(title,content,cover_img,state,category_id,create_user,create_time,update_time)"+
            "values (#{title},#{content},#{coverImg},#{state},#{categoryId},#{createUser},#{createTime},#{updateTime})")
    void add(Article article);
}

 2.文章列表(条件分页)

接口文档

实现

在controller里面添加方法,方法的返回类型为Result<PageBean<Article>>,(PageBean是我们自定义的一个对象,用来封装分页查询的结果,做分页查询的时候一般都会定义这个一个对象,里面至少包含两个属性,一个是total代表总条数,一个是items代表的是当前页面的数据集合)

方法上需要声明四个参数,分别接收前端传来四个参数。其中categoryId,state这两个参数是非必须传递的,因此需要在这两个参数前添加一个@RequestParam(required=false)注解,告诉MVC框架,这两个参数是非必须的。

在service层里面首先要构建一个PageBean对象,用它来封装将来查询的数据。

分页查询将来会借助mybatis提供的分页插件PageHelper,使用pageHelper进行分页查询的话,只需要在调用map的方法执行SQL之前,开启分页查询。(需要在pom.mxl文件中导入pagehelper的坐标)

<!--PageHelper坐标-->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper-spring-boot-starter</artifactId>
        <version>1.4.6</version>
    </dependency>

开启分页查询之后,调用map方法执行SQL就可以了。然后是条件搜索,前端有可能会传也可以不传,所以SQL不能写死,需要使用到myBatis的动态SQL技术来编写这段SQL了

代码:Controller层

   @GetMapping
   public Result<PageBean<Article>> list(
           Integer pageNum,
           Integer pageSize,
          @RequestParam(required = false) Integer categoryId,
           @RequestParam(required = false) String state
   ){
         PageBean<Article> pb= articleService.list(pageNum,pageSize,categoryId,state);
        return Result.success(pb);
   }

 Service层

//条件分页列表查询
     PageBean<Article> list(Integer pageNum, Integer pageSize, Integer categoryId, String state);

 Service接口实现层

    @Override
    public PageBean<Article> list(Integer pageNum, Integer pageSize, Integer categoryId, String state) {
        //1.创建PageBean对象
        PageBean<Article> pb=new PageBean<>();
        //2.开启分页查询PageHelper
        PageHelper.startPage(pageNum,pageSize);
        //3.调用mapper层查询
       Map<String,Object>map= ThreadLocalUtil.get();
       Integer userId = (Integer)map.get("id");
         List<Article> as = articleMapper.list(userId, categoryId,state);
         //Page中提供了方法,可以获取PageHelper分页查询后,得到的总记录条数和当前页数据,所以进行强转
         Page<Article> p = (Page<Article>) as;

         //把数据填充到PageBean中
        pb.setTatal(p.getTotal());
        pb.setItems(p.getResult());
        return pb;
    }

 Mapper层


    //查询
    List<Article> list(Integer userId, Integer categoryId, String state);

 在resources层下,建立与mapper相同路径的目录,新建配置文件编写映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.exampletest.mapper.ArticleMapper">
<!--    动态SQL-->
    <select id ="list" resultType="org.exampletest.pojo.Article">
        select * from article
        <where>
            <if test="categoryId!=null">
                category_id = #{categoryId}
            </if>
            <if test="state!=null">
               and state = #{state}
            </if>

                    and create_user = #{userId}
        </where>
    </select>
</mapper>

 结果:

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

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

相关文章

Day30 | 62.不同路径 63. 不同路径 II 343.整数拆分 96不同的二叉搜索树

语言 Java 62.不同路径 不同路径 题目 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问…

JVM类加载中的双亲委派机制

【1】什么是双亲委派 Java虚拟机对class文件采用的是按需加载的方式&#xff0c;也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象。而且加载某个类的class文件时&#xff0c;Java虚拟机采用的是双亲委派模式&#xff0c;即把请求交由父类处理&#xff0c…

【Git企业级开发实战指南①】Git安装、基本操作!

目录 一、Git是什么&#xff1f;1.1特点1.2功能1.3基本概念 二、Git安装2.1Ubuntu下安装2.2Centos下安装Git 三、Git基本操作3.1创建git本地仓库3.2配置Git3.3 工作区&暂存区&版本库3.4 实操案例3.4.1添加文件 3.5 修改文件3.6版本回退3.7查看历史操作日志3.7撤销修改3…

广东省各区县农业产量数据,数据精度至各区县,2020-2023年四年数据可选!

数据名称: 广东省各区县农业产量数据 数据格式: Shpexcel 数据几何类型: 面 数据坐标系: WGS84 数据时间&#xff1a;2020-2023年 数据来源&#xff1a;广东省统计年鉴 数据字段&#xff1a; 序号字段名称字段说明1province省份名称2city城市名称3county区县名称4cou…

【C++深度探索】红黑树的底层实现机制

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 &#x1f525; 所属专栏&#xff1a;C从入门至进阶 这里将会不定期更新有关C/C的内容&#xff0c;欢迎大家点赞&#xff0c;收藏&#xff0c;评论&#x1f973;&#x1f973;&#x1f389;&#x1f389;&#x1f389; 前言 红…

VNC未授权访问漏洞

VNC 是虚拟网络控制台Virtual Network Console的英文缩写。它是一款优秀的远程控制工具软件由美国电话电报公司AT&T的欧洲研究实验室开发。VNC是基于 UNXI 和 Linux 的免费开源软件由 VNC Server 和 VNC Viewer 两部分组成。VNC 默认端口号为 5900、5901。VNC 未授权访问漏…

STM32F407移植LVGL(V8.3版本)

一、LVGL简述 1.丰富且强大的模块化图形组件&#xff1a;按钮、图表、列表、滑条、图片等 2.高级图形引擎&#xff1a;动画、抗锯齿、透明度、平滑滚动、图层混合等效果 3.支持多种输入设备&#xff1a;触摸屏、键盘、编码器、按键等 4.配置可裁剪&#xff0c;最低资源占用&am…

latex中Function函数报错

latex写伪码时&#xff0c;发现报错&#xff0c;截图如下&#xff1a; 解决办法&#xff0c;添加宏包&#xff0c;截图如下&#xff1a; \usepackage{algpseudocode}

虚幻引擎 C++ 实现平面阴影

1、平面阴影介绍 平面阴影是一种相对简单的渲染阴影的方式&#xff0c;可以理解为对一个模型渲染两次&#xff0c;一次是渲染模型本身&#xff0c;另一次是渲染模型的投影。渲染投影可以看作是将模型的顶点变换到地面的投影空间再渲染&#xff0c;可以理解为渲染了一个“压扁”…

pytorch学习笔记6 tensor拼接和拆分

cat 合并 dim必须首选相同&#xff08;上例都是3&#xff09;&#xff0c;其次除了合并的dim&#xff08;上例中为dim0&#xff09;外&#xff0c;其它dim的size必须相同&#xff08;dim 1的size是32&#xff0c;dim2的size是8&#xff09;&#xff0c;否则需要手动处理到相同…

vue3 + Spingboot + oracle 通过Base64存储图片

一 、前言 近期在做vue3 Springboot oracle 的工作&#xff0c;有个小功能通过页面导入图片保存到oracle数据库中&#xff0c;本人对前端不是很熟悉&#xff0c;借此记录一下实现方法&#xff1b; 二、前端部分代码 <template><div class"dialog-mian"&…

SQL注入实例(sqli-labs/less-7)

0、初始页面 1、确定闭合字符 确定闭合字符为单引号括号括号 )) ?id1 and 11 ?id1 and 12 ?id1 ?id1)) 2、查看securie_file_priv参数 ?id1)) and upddatexml(1,concat(0x7e,(select secure_file_priv),0x7e),1) -- 3、写入一句话木马 ?id1)) union select null,&q…

SFT、RLHF、DPO、IFT —— LLM 微调的进化之路

TL;DR • SFT、RLHF 和 DPO 都是先估计 LLMs 本身的偏好&#xff0c;再与人类的偏好进行对齐&#xff1b; • SFT 只通过 LLMs 生成的下一个单词进行估计&#xff0c;而 RLHF 和 DPO 通过 LLMs 生成的完整句子进行估计&#xff0c;显然后者的估计会更准确&#xff1b; • 虽然…

壹连科技净利润增速放缓:毛利率清一色下滑,研发费用率远弱同行

《港湾商业观察》施子夫 王璐 从2022年6月20日递表创业板以来&#xff0c;深圳壹连科技股份有限公司&#xff08;以下简称&#xff0c;壹连科技&#xff09;已经走了2年多的历程&#xff0c;如今离挂牌上市近在咫尺。 今年7月22日&#xff0c;壹连科技提交了注册申请。8月2日…

哪个电脑桌面便签好用并且无广告弹窗?

在日常生活和工作中&#xff0c;很多人喜欢在电脑桌面上使用便签软件。便签软件可以方便地记录临时任务、重要信息或者待办事项&#xff0c;帮助用户更好地管理时间和提高工作效率。想象一下&#xff0c;在繁忙的工作中&#xff0c;你能够快速在桌面便签上记下即将要做的任务&a…

基本K8s搭建Jekins+gitee项目自动部署

这里写目录标题 1.基本K8s部署安装Jekins2.设置Jenkins国内镜像源2.安装Gitee插件1.安装Gitee Plugin2.验证安装Gitee Plugin 3.新建任务1.输入任务名称2.输入你gitee上的项目链接3.测试构建 4.查看项目在k8s集群master节点的位置1.确认 Jenkins Pod 名称2.使用kubectl exec到 …

大数据技术复习--概述

概述 数据的概念&#xff1a;数据是指对客观事件进行记录并可以鉴别的符号&#xff0c;是对客观事物的性质、状态以及相互关系等进行记载的物理符号或这些物理符号的组合&#xff0c;是可识别的、抽象的符号。 数据类型&#xff1a;文本、图片、音频、视频 从数据的结构化程…

2024华数杯全国大学生数学建模竞赛B题思路-VLSI电路单元的自动布局-MIA 感知的详细布局问题描述

本章主要对超大规模集成电路&#xff08;Very Large Scale Integration Circuit&#xff0c;VLSI&#xff09;布局 问题进行了描述&#xff0c;首先简单梳理一下超大规模集成电路设计流程、物理设计相关的知 识&#xff0c;接着对 MIA 感知的混合高度单元集成电路详细布局问题的…

vue之ref 属性

文章目录 1.ref 属性概述1.1 作用和特点 2.vue2用法2.1 获取 dom2.3 获取组件&#xff1a; 3.vue3用法 1.ref 属性概述 1.1 作用和特点 &#xff08;1&#xff09;作用&#xff1a;用来给元素或组件注册引用信息(相当于是id的替代者) &#xff08;2&#xff09;应用在HTML标签…

Kettle下载安装MySQL驱动教程

在 Windows 系统上下载适用于 MySQL 的 JDBC 驱动程序&#xff0c;您可以按照以下步骤操作&#xff1a; 1. 访问 MySQL 官方下载页面 打开浏览器&#xff1a; 打开您喜欢的浏览器。 访问 MySQL Connector/J 下载页面&#xff1a; 访问 MySQL Connector/J 下载页面. 2. 选择…