pageable redis缓存_pageable pageable - CSDN
精华内容
参与话题
  • redis缓存分页数据

    千次阅读 2017-09-23 14:45:11
    在我们开发项目的过程中,经常会对数据做分页展示,如果每次请求都去查询数据库,当访问量增大时,势必会加重数据库的负载,降低数据库性能。然而,有些数据的是极少...1、redis的hmset(key, value)方法,将key值设置

                         

             在我们开发项目的过程中,经常会对数据做分页展示,如果每次请求都去查询数据库,当访问量增大时,势必会加重数据库的负载,降低数据库性能。然而,有些数据的是极少变动的,或者说变动的频率不是很高,这时如果将这些数据进行缓存,不仅可以提高程序性能,还能降低数据库的负载。下面就给出高并发下的分页数据缓存方案。

    一、需要了解的一些知识点

    1、redis的hmset(key, value)方法,将key值设置为value,value是map类型的数据结构

    2、redis的hgetAll(key)方法,获取key的值,改值的类型为map类型的

    3、关键字synchronized

    4、key值包含的一些关键信息,前缀+当前的页数+每页数据的大小等

    二、代码实现

              
     /* (non-Javadoc)
    	 * 默认为60秒刷新一次;采用加锁模式应对高并发
    	 */
    	@Override
    	public Page<StrategySummary> getAdvisorStrategys(AdvisorCondition condition) throws IOException{
    		Pageable pageable=condition.getPage();
    		int currentPage = pageable.getPageNumber();
    		int pageSize = pageable.getPageSize();
    		Map<String,String> result=RedisUtil.getMap("advisor:"+condition.getId()+"_number:"+currentPage+"_size:"+pageSize, MARKET);
            if (result!=null&&result.size()>0) {
            	List<StrategySummary> dataList=JsonUtils.toJavaBeanList(result.get("data"), new TypeReference<List<StrategySummary>>() {});
            	long total=Long.valueOf(result.get("total"));
            	return new PageImplBean<StrategySummary>(dataList, pageable, total);	
    		} else {
    			Page<StrategySummary> page=null;
    			synchronized (MobileAppServiceImpl.class) {         //当首个线程将数据缓存后,后面的线程需再次检查,防止重复查询数据库和缓存数据
    				int count = 0;              
    				for (int i = 0; i < 3; i++) {                   //取3次,防止获取失败
    					Map<String,String> map =RedisUtil.getMap("advisor:"+condition.getId()+"_number:"+currentPage+"_size:"+pageSize, MARKET);
    					if (map==null||map.size()==0) {
    						continue;
    					}
    					if (map!=null&&map.size()>0) {
    						count++;
    						break;
    					}
    				}
    				if (count==0) {
    					page= mobileAppDao.getAdvisorStrategys(condition);
    					List<StrategySummary> dataList=page.getContent();
    					long total=page.getTotalElements();
    					if(dataList.size()>0){
    						Map<String, String> map=new HashMap<String,String>();
    						map.put("data", JsonUtils.toJsonString(dataList));
    						map.put("total", String.valueOf(total));
    						RedisUtil.setMapWithExpire("advisor:"+condition.getId()+"_number:"+currentPage+"_size:"+pageSize, map, MARKET);
    					}
    				}else{
    					Map<String,String> map =RedisUtil.getMap("advisor:"+condition.getId()+"_number:"+currentPage+"_size:"+pageSize, MARKET);
    					List<StrategySummary> dataList=JsonUtils.toJavaBeanList(map.get("data"), new TypeReference<List<StrategySummary>>() {});
    		        	long total=Long.valueOf(map.get("total"));
    		        	page= new PageImplBean<StrategySummary>(dataList, pageable, total);
    				}
    			}
    			return page;
    		}
    		
    	}

              
         
    展开全文
  • 查询Redis缓存

    2019-07-24 00:08:48
    package me.zhengjie.monitor.rest; import me.zhengjie.common.aop.log.Log; import me.zhengjie.monitor.domain.vo.RedisVo; ...import me.zhengjie.monitor.service.RedisService;...import org.springframewo...
    package me.zhengjie.monitor.rest;
    
    import me.zhengjie.common.aop.log.Log;
    import me.zhengjie.monitor.domain.vo.RedisVo;
    import me.zhengjie.monitor.service.RedisService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Pageable;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.security.access.prepost.PreAuthorize;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;
    
    /**
     * @author jie
     * @date 2018-12-10
     */
    @RestController
    @RequestMapping("api")
    public class RedisController {
    
        @Autowired
        private RedisService redisService;
    
        @Log(description = "查询Redis缓存")
        @GetMapping(value = "/redis")
        @PreAuthorize("hasAnyRole('ADMIN','REDIS_ALL','REDIS_SELECT')")
        public ResponseEntity getRedis(String key, Pageable pageable){
            return new ResponseEntity(redisService.findByKey(key,pageable), HttpStatus.OK);
        }
    
        @Log(description = "新增Redis缓存")
        @PostMapping(value = "/redis")
        @PreAuthorize("hasAnyRole('ADMIN','REDIS_ALL','REDIS_CREATE')")
        public ResponseEntity create(@Validated @RequestBody RedisVo resources){
            redisService.save(resources);
            return new ResponseEntity(HttpStatus.CREATED);
        }
    
        @Log(description = "修改Redis缓存")
        @PutMapping(value = "/redis")
        @PreAuthorize("hasAnyRole('ADMIN','REDIS_ALL','REDIS_EDIT')")
        public ResponseEntity update(@Validated @RequestBody RedisVo resources){
            redisService.save(resources);
            return new ResponseEntity(HttpStatus.NO_CONTENT);
        }
    
        @Log(description = "删除Redis缓存")
        @DeleteMapping(value = "/redis/{key}")
        @PreAuthorize("hasAnyRole('ADMIN','REDIS_ALL','REDIS_DELETE')")
        public ResponseEntity delete(@PathVariable String key){
            redisService.delete(key);
            return new ResponseEntity(HttpStatus.OK);
        }
    
        @Log(description = "清空Redis缓存")
        @DeleteMapping(value = "/redis/all")
        @PreAuthorize("hasAnyRole('ADMIN','REDIS_ALL','REDIS_DELETE')")
        public ResponseEntity deleteAll(){
            redisService.flushdb();
            return new ResponseEntity(HttpStatus.OK);
        }
    }
    package me.zhengjie.monitor.service.impl;
    
    import me.zhengjie.common.utils.PageUtil;
    import me.zhengjie.monitor.domain.vo.RedisVo;
    import me.zhengjie.monitor.service.RedisService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.domain.Page;
    import org.springframework.data.domain.PageImpl;
    import org.springframework.data.domain.Pageable;
    import org.springframework.stereotype.Service;
    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPool;
    import java.util.*;
    
    /**
     * @author jie
     * @date 2018-12-10
     */
    @Service
    public class RedisServiceImpl implements RedisService {
    
        @Autowired
        JedisPool pool;
    
        @Override
        public Page findByKey(String key, Pageable pageable){
            Jedis jedis = null;
            try{
                jedis = pool.getResource();
                List<RedisVo> redisVos = new ArrayList<>();
    
                if(!key.equals("*")){
                    key = "*" + key + "*";
                }
                for (String s : jedis.keys(key)) {
                    RedisVo redisVo = new RedisVo(s,jedis.get(s));
                    redisVos.add(redisVo);
                }
                Page<RedisVo> page = new PageImpl<RedisVo>(
                        PageUtil.toPage(pageable.getPageNumber(),pageable.getPageSize(),redisVos),
                        pageable,
                        redisVos.size());
                return page;
            }finally{
                if(null != jedis){
                    jedis.close(); // 释放资源还给连接池
                }
            }
    
        }
    
        @Override
        public void save(RedisVo redisVo) {
            Jedis jedis = null;
            try{
                jedis = pool.getResource();
                jedis.set(redisVo.getKey(),redisVo.getValue());
            }finally{
                if(null != jedis){
                    jedis.close(); // 释放资源还给连接池
                }
            }
        }
    
        @Override
        public void delete(String key) {
            Jedis jedis = null;
            try{
                jedis = pool.getResource();
                jedis.del(key);
            }finally{
                if(null != jedis){
                    jedis.close(); // 释放资源还给连接池
                }
            }
    
        }
    
        @Override
        public void flushdb() {
            Jedis jedis = null;
            try{
                jedis = pool.getResource();
                jedis.flushDB();
            }finally{
                if(null != jedis){
                    jedis.close(); // 释放资源还给连接池
                }
            }
    
        }
    }

     

    转载于:https://www.cnblogs.com/tonggc1668/p/11220922.html

    展开全文
  • 1 Springboot中使用redis,自动缓存、更新、删除

    万次阅读 热门讨论 2017-04-21 15:53:22
    springboot整合redis,如何用redis做分页查询,redis条件查询

    第一篇记录一下在springboot中,redis的基础用法,自动缓存新增的数据,自动修改及删除。

    在本机安装好mysql和redis。新建一个springboot的web项目,在新建项目时勾选redis,mysql。

    pom文件如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    
    	<groupId>com.tianyalei</groupId>
    	<artifactId>demo0</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    
    	<name>demo0</name>
    	<description>Demo project for Spring Boot</description>
    
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>1.5.2.RELEASE</version>
    		<relativePath/> <!-- lookup parent from repository -->
    	</parent>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<dependencies>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-jpa</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-redis</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>com.alibaba</groupId>
    			<artifactId>druid</artifactId>
    			<version>1.0.18</version>
    		</dependency>
    		<dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    			<scope>runtime</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>
    
    
    </project>
    

    数据库连接池用的druid,里面使用了spring-boot-starter-data-redis,有这一个依赖就够了,系统就能识别并应用redis了。dao工具用的jpa,默认集成了hibernate。

    下面配置一下application.yml。如下:

    spring:
      jpa:
        database: mysql
        show-sql: true
        hibernate:
          ddl-auto: update
      datasource:
          type: com.alibaba.druid.pool.DruidDataSource
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://localhost:3306/tx2
          username: root
          password:

    配置一下show-sql为true,目的是看看查表时的缓存效果。至于redis的ip,端口什么的都不用配,系统有个默认值,等会看看就知道了。 

    创建个java bean。

    package com.tianyalei.domain;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import java.io.Serializable;
    
    /**
     * Created by wuwf on 17/4/21.
     */
    @Entity
    public class Post implements Serializable{
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Integer id;
    
        private String content;
    
        private Integer weight;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
        public Integer getWeight() {
            return weight;
        }
    
        public void setWeight(Integer weight) {
            this.weight = weight;
        }
    }
    

    创建个repository

    package com.tianyalei.repository;
    
    import com.tianyalei.domain.Post;
    import org.springframework.cache.annotation.CacheConfig;
    import org.springframework.cache.annotation.CachePut;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.data.jpa.repository.Modifying;
    import org.springframework.data.repository.PagingAndSortingRepository;
    import org.springframework.transaction.annotation.Transactional;
    
    /**
     * Created by wuwf on 17/4/20.
     */
    @CacheConfig(cacheNames = "post")
    public interface PostRepository extends PagingAndSortingRepository<Post, Integer> {
        @Cacheable(key = "#p0")
        Post findById(int id);
    
        /**
         * 新增或修改时
         */
        @CachePut(key = "#p0.id")
        @Override
        Post save(Post post);
    
        @Transactional
        @Modifying
        int deleteById(int id);
    }
    
    这个里面有个CacheConfig,配置了cacheNames。

    我在findById方法时加了个@Cacheable(key= "#p0"),#p0代表第一个参数,也就是id。这句话加上之后,当你在调用findById时,就会先从redis的post缓存对象里去查询key等于传过来的id的值。如果没有,就去查表。

    在save方法上加了个CachePut,代表往缓存里添加值,key为参数post的id属性,这样当我们save一个Post对象时,redis就会新增一个以id为key的Post对象;如果是update操作,那同样,redis会覆盖id相同的Post对象的值,也完成一次更新。更多标签,请看http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html#cache-spel-context

    这样,在对post的新增和修改时都会自动缓存到redis里。

    下面来验证一下。

    加个service

    package com.tianyalei.service;
    
    import com.tianyalei.domain.Post;
    import com.tianyalei.repository.PostRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    
    /**
     * Created by wuwf on 17/4/20.
     */
    @Service
    public class PostService {
        @Autowired
        private PostRepository postRepository;
    
        public Post findById(int id) {
            return postRepository.findById(id);
        }
    
        public Post save(Post post) {
            return postRepository.save(post);
        }
    
        public int delete(int id) {
            return postRepository.deleteById(id);
        }
    }
    
    来个controller

    package com.tianyalei.controller;
    
    import com.tianyalei.domain.Post;
    import com.tianyalei.service.PostService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    
    /**
     * Created by wuwf on 17/4/20.
     */
    @RestController
    public class PostController {
        @Autowired
        private PostService postService;
    
        @RequestMapping("/query/{id}")
        public Object query(@PathVariable int id) {
            return postService.findById(id);
        }
    
        @RequestMapping("/save")
        public Object save(@ModelAttribute Post post) {
            return postService.save(post);
        }
    
        @RequestMapping("/delete/{id}")
        public Object delete(@PathVariable int id) {
            return postService.delete(id);
        }
    
        @RequestMapping("/queryPage")
        public Object query(String name, int pageNum, int count) {
            //根据weight倒序分页查询
    //        Pageable pageable = new PageRequest(pageNum, count, Sort.Direction.DESC, "weight");
    //        return userRepository.findByName(name, pageable);
            return null;
        }
    }
    
    然后启动Application,在启动之前需要加上@EnableCaching注解,缓存才能正常工作。

    package com.tianyalei;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cache.annotation.EnableCaching;
    
    @SpringBootApplication
    @EnableCaching
    public class Demo0Application {
    
    	public static void main(String[] args) {
    		SpringApplication.run(Demo0Application.class, args);
    	}
    }
    
    启动后访问 http://localhost:8080/save?content=1&weight=1

    这样就添加了一条记录,控制台有一个insert语句。

    然后访问查询,http://localhost:8080/query/1

    会发现查询到了id为1的这条记录,并且控制台没有走select查询语句,也就是根本没访问数据库,直接从redis缓存拿的值。

    下面做一个更新操作,看看是否会同步到redis里。http://localhost:8080/save?content=1&weight=2&id=1

    把weight改为2,访问地址看看结果。

    控制台打印了两条语句

    Hibernate: select post0_.id as id1_0_0_, post0_.content as content2_0_0_, post0_.weight as weight3_0_0_ from post post0_ where post0_.id=?
    Hibernate: update post set content=?, weight=? where id=?

    说明数据已经被更新了。然后再查询http://localhost:8080/query/1

    发现查到的数据已经改变,并且控制台没有走select语句,说明在update时,redis已经更新了。

    下面做删除操作,可以直接在数据库里删这条记录,或者通过浏览器访问来删除。http://localhost:8080/delete/1

    控制台走了删除delete语句。再访问查询地址。发现依旧能查到这条记录,也就是db的删除成功了,但redis并没有删除。

    那么怎么在db删除时,也删除redis的相关记录呢?

    用CacheEvict

    @CacheConfig(cacheNames = "post")
    public interface PostRepository extends PagingAndSortingRepository<Post, Integer> {
        @Cacheable(key = "#p0")
        Post findById(int id);
    
        /**
         * 新增或修改时
         */
        @CachePut(key = "#p0.id")
        @Override
        Post save(Post post);
    
        @Transactional
        @Modifying
        @CacheEvict(key = "#p0")
        int deleteById(int id);
    }
    
    加上这个标签后,再走deleteById方法时,就会删除掉key为id的redis记录了。可以重启试试,访问http://localhost:8080/delete/1

    然后再查询就会发现id为1的值已经查不到了。

    这样我们就完成了一个最简单的整合redis的demo。包括了对单个对象的增删改查的缓存。

    那么下面来讲几个疑问:

    1.为什么不用配置redis的地址,port,密码什么的?

    上面的那些默认的对redis的操作,来源于Springboot里整合的RedisTemplate,template里会默认使用一个JedisConnectionFactory来做默认的连接属性配置。



    这里面已经对jedis的连接地址和jedisPool做了初始化操作了,都是默认值。系统就会使用这些默认值来操作redis。

    后面我们会对Connection进行自定义,设置value的序列化方式,还有修改连接地址,那时就会使用自定义的配置了。

    2.能否用上面的方法来存储集合?譬如所有的Post集合,当新增时集合也随之改变?

    不行的,假如给List<Post> findAll做了个缓存,那下次查询时确实不用查表了,但是当你新增、修改、删除任何一个对象时,这个缓存的集合都是不变的。

    除非你在所有的能修改对象的地方,都加上CacheEvict,key为集合的key,这样任何修改,都是删除整个集合对象的缓存,下次再查时才能缓存起来。而大部分时候,集合对象都是在不停变化的,除了一些不变的如城市列表之类的,其他的都不适合用这种缓存方式。会导致频繁创建大对象,而且大部分时候也不需要查整个集合,而是分页。

    3.怎么用redis来做集合查询,分页查询,甚至于条件分页查询?

    这个也是问题2的延续,后面一篇会讲。








    展开全文
  • 第一篇记录一下在springboot中,redis的基础用法,自动缓存新增的数据,自动修改及删除。 在本机安装好mysql和redis。新建一个springboot的web项目,在新建项目时勾选redis,mysql。 pom文件如下: <?xml ...

    原文格式更清晰:https://cloud.tencent.com/developer/article/1383997

     

    第一篇记录一下在springboot中,redis的基础用法,自动缓存新增的数据,自动修改及删除。

    在本机安装好mysql和redis。新建一个springboot的web项目,在新建项目时勾选redis,mysql。

    pom文件如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    
    	<groupId>com.tianyalei</groupId>
    	<artifactId>demo0</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    
    	<name>demo0</name>
    	<description>Demo project for Spring Boot</description>
    
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>1.5.2.RELEASE</version>
    		<relativePath/> <!-- lookup parent from repository -->
    	</parent>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<dependencies>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-jpa</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-data-redis</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<dependency>
    			<groupId>com.alibaba</groupId>
    			<artifactId>druid</artifactId>
    			<version>1.0.18</version>
    		</dependency>
    		<dependency>
    			<groupId>mysql</groupId>
    			<artifactId>mysql-connector-java</artifactId>
    			<scope>runtime</scope>
    		</dependency>
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-test</artifactId>
    			<scope>test</scope>
    		</dependency>
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>
    
    
    </project>

    数据库连接池用的druid,里面使用了spring-boot-starter-data-redis,有这一个依赖就够了,系统就能识别并应用redis了。dao工具用的jpa,默认集成了hibernate。

    下面配置一下application.yml。如下:

    spring:
      jpa:
        database: mysql
        show-sql: true
        hibernate:
          ddl-auto: update
      datasource:
          type: com.alibaba.druid.pool.DruidDataSource
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://localhost:3306/tx2
          username: root
          password:

    配置一下show-sql为true,目的是看看查表时的缓存效果。至于redis的ip,端口什么的都不用配,系统有个默认值,等会看看就知道了。 

    创建个java bean。

    package com.tianyalei.domain;
    
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import java.io.Serializable;
    
    /**
     * Created by wuwf on 17/4/21.
     */
    @Entity
    public class Post implements Serializable{
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Integer id;
    
        private String content;
    
        private Integer weight;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
        public Integer getWeight() {
            return weight;
        }
    
        public void setWeight(Integer weight) {
            this.weight = weight;
        }
    }

    创建个repository

    package com.tianyalei.repository;
    
    import com.tianyalei.domain.Post;
    import org.springframework.cache.annotation.CacheConfig;
    import org.springframework.cache.annotation.CachePut;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.data.jpa.repository.Modifying;
    import org.springframework.data.repository.PagingAndSortingRepository;
    import org.springframework.transaction.annotation.Transactional;
    
    /**
     * Created by wuwf on 17/4/20.
     */
    @CacheConfig(cacheNames = "post")
    public interface PostRepository extends PagingAndSortingRepository<Post, Integer> {
        @Cacheable(key = "#p0")
        Post findById(int id);
    
        /**
         * 新增或修改时
         */
        @CachePut(key = "#p0.id")
        @Override
        Post save(Post post);
    
        @Transactional
        @Modifying
        int deleteById(int id);
    }

    这个里面有个CacheConfig,配置了cacheNames。

    我在findById方法时加了个@Cacheable(key= "#p0"),#p0代表第一个参数,也就是id。这句话加上之后,当你在调用findById时,就会先从redis的post缓存对象里去查询key等于传过来的id的值。如果没有,就去查表。

    在save方法上加了个CachePut,代表往缓存里添加值,key为参数post的id属性,这样当我们save一个Post对象时,redis就会新增一个以id为key的Post对象;如果是update操作,那同样,redis会覆盖id相同的Post对象的值,也完成一次更新。更多标签,请看http://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html#cache-spel-context

    这样,在对post的新增和修改时都会自动缓存到redis里。

    下面来验证一下。

    加个service

    package com.tianyalei.service;
    
    import com.tianyalei.domain.Post;
    import com.tianyalei.repository.PostRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    
    /**
     * Created by wuwf on 17/4/20.
     */
    @Service
    public class PostService {
        @Autowired
        private PostRepository postRepository;
    
        public Post findById(int id) {
            return postRepository.findById(id);
        }
    
        public Post save(Post post) {
            return postRepository.save(post);
        }
    
        public int delete(int id) {
            return postRepository.deleteById(id);
        }
    }

    来个controller

    package com.tianyalei.controller;
    
    import com.tianyalei.domain.Post;
    import com.tianyalei.service.PostService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.ModelAttribute;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    
    /**
     * Created by wuwf on 17/4/20.
     */
    @RestController
    public class PostController {
        @Autowired
        private PostService postService;
    
        @RequestMapping("/query/{id}")
        public Object query(@PathVariable int id) {
            return postService.findById(id);
        }
    
        @RequestMapping("/save")
        public Object save(@ModelAttribute Post post) {
            return postService.save(post);
        }
    
        @RequestMapping("/delete/{id}")
        public Object delete(@PathVariable int id) {
            return postService.delete(id);
        }
    
        @RequestMapping("/queryPage")
        public Object query(String name, int pageNum, int count) {
            //根据weight倒序分页查询
    //        Pageable pageable = new PageRequest(pageNum, count, Sort.Direction.DESC, "weight");
    //        return userRepository.findByName(name, pageable);
            return null;
        }
    }

    然后启动Application,在启动之前需要加上@EnableCaching注解,缓存才能正常工作。

    package com.tianyalei;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cache.annotation.EnableCaching;
    
    @SpringBootApplication
    @EnableCaching
    public class Demo0Application {
    
    	public static void main(String[] args) {
    		SpringApplication.run(Demo0Application.class, args);
    	}
    }

    启动后访问 http://localhost:8080/save?content=1&weight=1

    这样就添加了一条记录,控制台有一个insert语句。

    然后访问查询,http://localhost:8080/query/1

    会发现查询到了id为1的这条记录,并且控制台没有走select查询语句,也就是根本没访问数据库,直接从redis缓存拿的值。

    下面做一个更新操作,看看是否会同步到redis里。http://localhost:8080/save?content=1&weight=2&id=1

    把weight改为2,访问地址看看结果。

    控制台打印了两条语句

    Hibernate: select post0_.id as id1_0_0_, post0_.content as content2_0_0_, post0_.weight as weight3_0_0_ from post post0_ where post0_.id=? Hibernate: update post set content=?, weight=? where id=?

    说明数据已经被更新了。然后再查询http://localhost:8080/query/1

    发现查到的数据已经改变,并且控制台没有走select语句,说明在update时,redis已经更新了。

    下面做删除操作,可以直接在数据库里删这条记录,或者通过浏览器访问来删除。http://localhost:8080/delete/1

    控制台走了删除delete语句。再访问查询地址。发现依旧能查到这条记录,也就是db的删除成功了,但redis并没有删除。

    那么怎么在db删除时,也删除redis的相关记录呢?

    用CacheEvict

    @CacheConfig(cacheNames = "post")
    public interface PostRepository extends PagingAndSortingRepository<Post, Integer> {
        @Cacheable(key = "#p0")
        Post findById(int id);
    
        /**
         * 新增或修改时
         */
        @CachePut(key = "#p0.id")
        @Override
        Post save(Post post);
    
        @Transactional
        @Modifying
        @CacheEvict(key = "#p0")
        int deleteById(int id);
    }

    加上这个标签后,再走deleteById方法时,就会删除掉key为id的redis记录了。可以重启试试,访问http://localhost:8080/delete/1

    然后再查询就会发现id为1的值已经查不到了。

    这样我们就完成了一个最简单的整合redis的demo。包括了对单个对象的增删改查的缓存。

    那么下面来讲几个疑问:

    1.为什么不用配置redis的地址,port,密码什么的?

    上面的那些默认的对redis的操作,来源于Springboot里整合的RedisTemplate,template里会默认使用一个JedisConnectionFactory来做默认的连接属性配置。

    这里面已经对jedis的连接地址和jedisPool做了初始化操作了,都是默认值。系统就会使用这些默认值来操作redis。

    后面我们会对Connection进行自定义,设置value的序列化方式,还有修改连接地址,那时就会使用自定义的配置了。

    2.能否用上面的方法来存储集合?譬如所有的Post集合,当新增时集合也随之改变?

    不行的,假如给List<Post> findAll做了个缓存,那下次查询时确实不用查表了,但是当你新增、修改、删除任何一个对象时,这个缓存的集合都是不变的。

    除非你在所有的能修改对象的地方,都加上CacheEvict,key为集合的key,这样任何修改,都是删除整个集合对象的缓存,下次再查时才能缓存起来。而大部分时候,集合对象都是在不停变化的,除了一些不变的如城市列表之类的,其他的都不适合用这种缓存方式。会导致频繁创建大对象,而且大部分时候也不需要查整个集合,而是分页。

    3.怎么用redis来做集合查询,分页查询,甚至于条件分页查询?

    这个也是问题2的延续,后面一篇会讲。

     

    转载自:https://cloud.tencent.com/developer/article/1383997

    展开全文
  • 本文基于 SpringCloud, 用户发起点赞、取消点赞后先存入 Redis 中,再每隔两小时从 Redis 读取点赞数据写入数据库中做持久化存储。 点赞功能在很多系统中都有,但别看功能小,想要做好需要考虑的东西还挺多的。 点赞...
  • 本文基于 SpringCloud, 用户发起点赞、取消点赞后先存入 Redis 中,再每隔两小时从 Redis 读取点赞数据写入数据库中做持久化存储。 点赞功能在很多系统中都有,但别看功能小,想要做好需要考虑的东西还挺多的。 ...
  • redis 缓存

    2019-05-17 22:36:04
    --缓存依赖,此处不再需要,因为他的包在其他依赖中已经有了 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artif...
  • 本文基于 SpringCloud, 用户发起点赞、取消点赞后先存入 Redis 中,再每隔两小时从 Redis 读取点赞数据写入数据库中做持久化存储。 点赞功能在很多系统中都有,但别看功能小,想要做好需要考虑的东西还挺多的。 点赞...
  • 本文基于 SpringCloud, 用户发起点赞、取消点赞后先存入 Redis 中,再每隔两小时从 Redis 读取点赞数据写入数据库中做持久化存储。点赞功能在很多系统中...
  • 作者丨solocoderjuejin.im/post/5bdc257e6fb9a049ba410098本文基于 SpringCloud, 用户发起点赞、取消点赞后先存入 ...
  • 作者:solocoderjuejin.im/post/5bdc257e6fb9a049ba410098本文基于 SpringCloud, 用户发起点赞、取消点赞后先存入 ...
  • Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。 换句话说,Redis就像是一个HashMap,不过不是在JVM中运行,而是以一个独立进程的形式运行...
  • 1,实际工程代码 ...redis.database=0 redis.host={sc} redis.port=6379 接口 package com.mylib.elba.cache.service; import com.mylib.elba.cache.entity.CacheManage; import com.mylib.Pag...
  • 本文基于 SpringCloud, 用户发起点赞、取消点赞后先存入 Redis 中,再每隔两小时从 Redis 读取点赞数据写入数据库中做持久化存储。 点赞功能在很多系统中都有,但别看功能小,想要做好需要考虑的东西还挺多的。 点赞...
  • 本文基于 SpringCloud, 用户发起点赞、取消点赞后先存入 Redis 中,再每隔两小时从 Redis 读取点赞数据写入数据库中做持久化存储。 点赞功能在很多系统中都有,但别看功能小,想要做好需要考虑的东西还挺多的。 ...
1 2 3 4 5 ... 20
收藏数 514
精华内容 205
关键字:

pageable redis缓存