个人博客 毕业设计2-(包含redis)

一、继续做base模块

下面来点JPA的高级操作

1、标签查找

在这里插入图片描述
标签分页,请求路径没问题,传进来的东西是一个Label类,模糊查找labelname和精准查找state,那就要转换一下了

controller

    @PostMapping("search")
    public Result findSearch(@RequestBody Label label){
    
    
        System.out.println(label);
        List<Label> list = labelService.findSearch(label);
        return new Result(true,StatusCode.OK,"查询成功",list);
    }

service

public List<Label> findSearch(Label label) {
    
    
  /*
  返回一个List集合,这个是模糊查找嘛,就labelname和state是有可能查找的,就这两个查找
   */
  return labelDao.findAll(new Specification<Label>() {
    
    
      @Override
      public Predicate toPredicate(Root<Label> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
    
    
          //new一个list集合,用来存放所有条件,因为直接and不行,有if条件在
          List<Predicate> list = new ArrayList<>();

          //当labelname不为空的时候
          if (label.getLabelname()!=null&&!"".equals(label.getLabelname())){
    
    
              Path<Object> labelname = root.get("labelname");
              Predicate predicate1 = criteriaBuilder.like(labelname.as(String.class), "%" + label.getLabelname() + "%");//where labelname like xxx
              list.add(predicate1);
          }

          //当state不为空的时候
          if (label.getState()!=null&&!"".equals(label.getState())){
    
    
              Path<Object> state = root.get("state");
//                    Predicate predicate2 = criteriaBuilder.like(state.as(String.class), "%" + label.getState() + "%");//where state like xxx
              Predicate predicate2 = criteriaBuilder.equal(state, label.getState());
              list.add(predicate2);
          }

          //因为不知道Predicate长度,但是list不用知道长度,把list转换成数组就行
          Predicate[] parr = new Predicate[list.size()];
          parr = list.toArray(parr);

          //and()参数 Predicate[]
          return criteriaBuilder.and(parr);//where state like xxx and labelname like xxx

      }
  });
}

在这里插入图片描述

2、标签+分页查找

先看需求
在这里插入图片描述
在这里插入图片描述
这个返回的data类型,第一个是总数据量,第二个才是那一页的的数据
controller:

@PostMapping("search/{page}/{size}")
    public Result findSearchPage(@RequestBody Label label,@PathVariable("page") int page,@PathVariable("size") int size){
    
    
        Page<Label> pageData = labelService.findSearchPage(label,page,size);
        //返回的data为PageResult类,其第一个是总数量,第二个是数据
        return new Result(true,StatusCode.OK,"查询成功",new PageResult<Label>((int) pageData.getTotalElements(),pageData.getContent()));
    }
public Page<Label> findSearchPage(Label label, int page, int size) {
    
    
    Specification<Label> specification = new Specification<Label>() {
    
    
        @Override
        public Predicate toPredicate(Root<Label> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
    
    
            //new一个list集合,用来存放所有条件,因为直接and不行,有if条件在
            List<Predicate> list = new ArrayList<>();

            //当labelname不为空的时候
            if (label.getLabelname()!=null&&!"".equals(label.getLabelname())){
    
    
                Path<Object> labelname = root.get("labelname");
                Predicate predicate1 = criteriaBuilder.like(labelname.as(String.class), "%" + label.getLabelname() + "%");//where labelname like xxx
                list.add(predicate1);
            }

            //当state不为空的时候
            if (label.getState()!=null&&!"".equals(label.getState())){
    
    
                Path<Object> state = root.get("state");
//                    Predicate predicate2 = criteriaBuilder.like(state.as(String.class), "%" + label.getState() + "%");//where state like xxx
                Predicate predicate2 = criteriaBuilder.equal(state, label.getState());
                list.add(predicate2);
            }

            //因为不知道Predicate长度,但是list不用知道长度,把list转换成数组就行
            Predicate[] parr = new Predicate[list.size()];
            parr = list.toArray(parr);

            //and()参数 Predicate[]
            return criteriaBuilder.and(parr);//where state like xxx and labelname like xxx
        }
    };
    Pageable pageable = PageRequest.of(page-1,size);//因为查询是从0开始的
    return labelDao.findAll(specification,pageable);
}

controller用PageResult<T>接受,这个在tensquare_commom模板中已经写好了,所以,准确的说这也是个POJO

在这里插入图片描述

二、招聘模块

普通的增删改查都很简单,我们主要来看特殊一点的

1、使用代码生成器(偷懒)

由于数据库表之前都做了,搭建基本的包什么的都是很简单的,用IT黑马给的代码生成器自动生成
在这里插入图片描述
然后对其拉入到tensquare目录下,对其进行简单的修改
在这里插入图片描述
在这里插入图片描述

1)修改父文件pom

在这里插入图片描述

2)修改招聘模块pom文件

在这里插入图片描述
这两个直接抄base模块的就可以

3)改下Application

就是原本是在这里插入图片描述
改成RecruitApplication而已,这样Application就不混乱了

4)改yml文件

修改端口号,还有url不要useUnicode=true&amp;

server: 
  port: 9002
spring: 
  application:  
    name: tensquare-recruit #指定服务名
  datasource:  
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://192.168.12.128:3306/tensquare_recruit?characterEncoding=UTF8
    username: root
    password: root
  jpa: 
    database: MySQL
    show-sql: true

其自动生成了我们之前敲的东西(不亏是教育机构)

5)可以的话改下controller请求和@RequestBody的参数

这个设及的东西太多,慢慢改。。都是体力活
改成@GETMapping这些
然后是@RequestBody都是Map,但我还是喜欢直接用类来做,这样一改,底层就要全部改了,工作量太大了。。。但是不改也不是不能用

6)表的BUG

那个表啊,好起不起,有个列为condition,而数据库列名的关键字为连接里面的表
https://blog.csdn.net/findmyself_for_world/article/details/43225555

解决办法:
https://blog.csdn.net/lose_alan/article/details/105510504

2、业务说明与数据库说明

先看下完成的模板
在这里插入图片描述
要的是推荐职位、最新职位、热门企业这3个部分
先说下数据库,当初建表的时候没说,现在说
分为两个表,企业表和招聘表
在这里插入图片描述
在这里插入图片描述
是否热门企业就ishot的变化,推荐职位就是state为2的状态,最新职位就直接按时间推算就行

3、查询热门企业

在这里插入图片描述

就一个很简单的东西,就查ishot是不是为1就行了,应该忘了。。
dao:

public interface EnterpriseDao extends JpaRepository<Enterprise,String>,JpaSpecificationExecutor<Enterprise>{
    
    
	public List<Enterprise> findByIshot(String ishot);
}

service

public List<Enterprise> findByIshot(String ishot){
    
    
		return enterpriseDao.findByIshot(ishot);
	}

controller

@GetMapping("search/hotlist")
	public Result hotlist(){
    
    
		List<Enterprise> enterprises = enterpriseService.findByIshot("1");
		return new Result(true,StatusCode.OK,"查询成功",enterprises);
	}

4、推荐职位与最新职位

推荐职位:state为2等于推荐,找前6个即可,并且根据时间顺序排序
最新职位:state不为0(不关闭),前6个,并且根据时间顺序排序,
在这里插入图片描述
在这里插入图片描述

public interface RecruitDao extends JpaRepository<Recruit,String>,JpaSpecificationExecutor<Recruit>{
    
    
    //推荐职位
	public List<Recruit> findTop6ByStateOrderByCreatetimeDesc(String state);

	//最新职位
    public List<Recruit> findTop6ByStateNotOrderByCreatetimeDesc(String state);
}

service

public List<Recruit> findTop6ByStateOrderByCreatetimeDesc(){
    
    
	return recruitDao.findTop6ByStateOrderByCreatetimeDesc("2");
}

public List<Recruit> findTop6ByStateNotOrderByCreatetimeDesc(){
    
    
	return recruitDao.findTop6ByStateNotOrderByCreatetimeDesc("0");
}

controller

@GetMapping("search/recommend")
public Result findTop6ByStateOrderByCreatetimeDesc(){
    
    
	List<Recruit> recruits = recruitService.findTop6ByStateOrderByCreatetimeDesc();
	return new Result(true,StatusCode.OK,"查询成功",recruits);
}

@GetMapping("search/newlist")
public Result findTop6ByStateNotOrderByCreatetimeDesc(){
    
    
	List<Recruit> recruits = recruitService.findTop6ByStateNotOrderByCreatetimeDesc();
	return new Result(true,StatusCode.OK,"查询成功",recruits);
}

在这里插入图片描述
在这里插入图片描述

三、问答模块

1、关系说明

问答长这样
在这里插入图片描述
一个问题可以对应多个标签(php,js),一个标签可以有多个问题,多对多关系,建立中间表。
一个问题对应多个回答,1对多
在这里插入图片描述
这个触发器和跨数据库连接表的,还没做,也不会做。。。

2、代码生成

然后也是用代码生成器,改端口9003,改父与子的pom文件

3、最新、热门、等待回答列表

在这里插入图片描述
在这里插入图片描述
3个表的传入传出参数都一样,对应表一起来看
在这里插入图片描述
最新问题就按照最新回复时间排序,热门就根据reply顺序排序,等待回答就reply为0的,注意这里要用多表连接了,因为要根据连接标签号ID查找列表(就是tb_problem连接tb_pl表啦,问题ID与标签号连接)

热门回答:回复数从高到低
最新回答:最新回复时间
等待回答:回复数为0

1)dao用sql语句

public interface ProblemDao extends JpaRepository<Problem,String>,JpaSpecificationExecutor<Problem>{
    
    

    @Query(value ="SELECT * FROM `tb_problem` as `p`,`tb_pl` as `pl` where p.id = pl.problemid and pl.labelid = ? ORDER BY replytime DESC",nativeQuery=true)
    public Page<Problem> newList(String id, Pageable pageable);

    @Query(value ="SELECT * FROM `tb_problem` as `p`,`tb_pl` as `pl` where p.id = pl.problemid and pl.labelid = ? ORDER BY reply DESC",nativeQuery=true)
    public Page<Problem> hotList(String id,Pageable pageable);

    @Query(value ="SELECT * FROM `tb_problem` as `p`,`tb_pl` as `pl` where p.id = pl.problemid and pl.labelid = ? and p.reply = 0  ORDER BY replytime DESC",nativeQuery=true)
    public Page<Problem> waitList(String id,Pageable pageable);

}

2)service

public Page<Problem> newList(String id,int page,int size){
    
    
	return problemDao.newList(id, PageRequest.of(page-1, size));
}

public Page<Problem> hotList(String id,int page,int size){
    
    
	return problemDao.hotList(id, PageRequest.of(page-1, size));
}

public Page<Problem> waitList(String id,int page,int size){
    
    
	return problemDao.waitList(id, PageRequest.of(page-1, size));
}

3)controller

@GetMapping("newlist/{labelid}/{page}/{size}")
public Result newList(@PathVariable("labelid") String labelid,@PathVariable int page,@PathVariable int size){
    
    
	Page<Problem> problems = problemService.newList(labelid, page, size);
	return new Result(true,StatusCode.OK,"查找成功",new PageResult(problems.getTotalElements(),problems.getContent()));
}

@GetMapping("hotlist/{labelid}/{page}/{size}")
public Result hotList(@PathVariable("labelid") String labelid,@PathVariable int page,@PathVariable int size){
    
    
	Page<Problem> problems = problemService.hotList(labelid, page, size);
	return new Result(true,StatusCode.OK,"查找成功",new PageResult(problems.getTotalElements(),problems.getContent()));
}

@GetMapping("waitlist/{labelid}/{page}/{size}")
public Result waitList(@PathVariable("labelid") String labelid,@PathVariable int page,@PathVariable int size){
    
    
	Page<Problem> problems = problemService.waitList(labelid, page, size);
	return new Result(true,StatusCode.OK,"查找成功",new PageResult( problems.getTotalElements(),problems.getContent()));
}

四、文章模块

继续代码生成
在这里插入图片描述

1、文章审核与点赞

都比较简单,但是注意要用事务性@Transactional注解,否则会出错
在这里插入图片描述

1)dao

@Transactional
public interface ArticleDao extends JpaRepository<Article,String>,JpaSpecificationExecutor<Article>{
    
    

    @Modifying
    @Query(value = "update tb_article set state = 1 where id = ?",nativeQuery = true)
    public void examine(String id);

    @Modifying
    @Query(value = "update tb_article set thumbup = thumbup + 1 where id = ?",nativeQuery = true)
    public void thumbup(String id);
}

2)service和controller

public void examine(String id){
    
    
	articleDao.examine(id);
}

public void thumbup(String id){
    
    
	articleDao.thumbup(id);
}
@PutMapping("examine/{articleId}")
public Result examine(@PathVariable String articleId){
    
    
	articleService.examine(articleId);
	return new Result(true,StatusCode.OK,"审核成功");
}

@PutMapping("thumbup/{articleId}")
public Result thumbup(@PathVariable String articleId){
    
    
	articleService.thumbup(articleId);
	return new Result(true,StatusCode.OK,"点赞成功");
}

五、redis

redis都知道了,就是缓冲的东西,已经查过的东西不要丢,放在redis缓冲中,再次查找就从redis中找数据,减少数据库压力

1、安装

在docker容器中安装,我们已经安装了,就直接启用就行
docker run -di --name=tensquare_redis -p 6379:6379 redis

  • redis端口号为6379

在这里插入图片描述

2、使用步骤

1)导包

	  <dependency>
		  <groupId>org.springframework.boot</groupId>
		  <artifactId>spring-boot-starter-data-redis</artifactId>
	  </dependency>

2)改yml

spring: 
  redis:
    host: 192.168.12.128:6379

3)将数据缓冲(查找ID例子)

在这里插入图片描述

在这里插入图片描述
执行一次查找一次,将改方法加入redis缓冲中

service:

@Service
public class ArticleService {
    
    

	@Autowired
	private ArticleDao articleDao;
	
	@Autowired
	private IdWorker idWorker;

	//自动导入RedisTemplate,主要就是靠这个类
	@Autowired
	private RedisTemplate redisTemplate;
	
	public Article findById(String id) {
    
    
		//先从缓冲中查询当前对象
		Article article = (Article)redisTemplate.opsForValue().get("article_" + id);
		//如果没有取到的话
		if (article==null){
    
    
			//那就从数据库中查询
			article = articleDao.findById(id).get();
			//然后把值存入到缓冲中
			redisTemplate.opsForValue().set("article_"+id,article);
		}
		return article;
	}

4)删除缓冲

值得一提的是,如果你update或者delete的时候,redis中的缓冲不会自动删除,所以要在更新和删除语句中使用删除缓冲语句

	public void update(Article article) {
    
    
		redisTemplate.delete("article_"+article.getId());
		articleDao.save(article);
	}

	public void deleteById(String id) {
    
    
		redisTemplate.delete("article_"+id);
		articleDao.deleteById(id);
	}

5)基本语法

stringRedisTemplate.opsForValue().set("test", "100",60*10,TimeUnit.SECONDS);//向redis里存入数据和设置缓存时间
stringRedisTemplate.opsForValue().get("test")//根据key获取缓存中的val
stringRedisTemplate.boundValueOps("test").increment(-1);//val做-1操作
stringRedisTemplate.boundValueOps("test").increment(1);//val +1
stringRedisTemplate.getExpire("test")//根据key获取过期时间
stringRedisTemplate.getExpire("test",TimeUnit.SECONDS)//根据key获取过期时间并换算成指定单位
stringRedisTemplate.delete("test");//根据key删除缓存
stringRedisTemplate.hasKey("546545");//检查key是否存在,返回boolean值
stringRedisTemplate.expire("red_123",1000 , TimeUnit.MILLISECONDS);//设置过期时间
stringRedisTemplate.opsForSet().add("red_123", "1","2","3");//向指定key中存放set集合
stringRedisTemplate.opsForSet().isMember("red_123", "1")//根据key查看集合中是否存在指定数据
stringRedisTemplate.opsForSet().members("red_123");//根据key获取set集合

6)总结

导包改yml,导入RedisTemplate ,RedisTemplate查找,如果没有就设值
其实最主要就只是redisTemplate.opsForValue().get(下标);来查找值,和redisTemplate.opsForValue().set(下标,值);来设置缓冲下标与对应值
但建议还是弄个redis工具类,把东西都写好,这样就不用一个一个写这么麻烦了

猜你喜欢

转载自blog.csdn.net/yi742891270/article/details/109457232