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

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>

 结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值