【redis-01】redis整合springboot实现简单的增删改查

【一】基本的环境配置

(1)添加相关的依赖

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

        <!-- Jedis客户端依赖 -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.3.0</version>
        </dependency>

        <!-- redisson -->
        <dependency>
            <groupId>org.redisson</groupId>
            <artifactId>redisson</artifactId>
            <version>3.6.5</version>
        </dependency>

        <!-- 通用池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

        <!-- mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.21</version>
        </dependency>

        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <!-- 不想写sql,通用mapper -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>

        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- test测试用例 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

    </dependencies>

(2)添加配置

server.port=8080

#mysql数据源
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/suanzhang?characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jpa.properties.hibernate.hbm2ddl.auto=update

###########################redis#########################
#Redis数据库索引(默认为0)
spring.redis.database=0
#Redis服务器地址
spring.redis.host=127.0.0.1
#Redis服务器连接端口
spring.redis.port=6379
#Redis服务器连接密码(默认为空)
spring.redis.password=

spring.jpa.show-sql=true

#打印sql
logging.level.com.allen.hello_redis.Mapper:debug

【二】基本的代码准备

(1)准备数据库和数据表

(2)创建实体类

public class EmployeeTemp {
    private int id;
    private String name;

    //手动添加无参构造方法,否则会出现redis反序列化失败的情况
    public EmployeeTemp(){

    };
    public EmployeeTemp(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

(3)创建mapper层

@Mapper
public interface EmpMapper{

    @Select("select * from employee where id = #{id}")
    public Employee findEmpById(int id);

    @Delete("delete from employee where id=#{id}")
    public void deleteEmpById(int id);

    @Update("update employee set name=#{name} where id=#{id}")
    public void update(Employee employee);

    @Insert("insert into employee (name) values (#{name})")
    public int insert01(Employee employee);

    @Select("select * from employee")
    public List<Employee> findAll();

    @Select("delete from employee")
    public void deleteAll();
}

(4)创建service层

@Service
@Slf4j
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    EmpMapper empMapper;

    @Autowired
    public RedisTemplate redisTemplate;

    /*第二部分:不使用注解实现操作redis和mysql数据*/
    @Override
    public void insert01(EmployeeTemp employeeTemp) {
        Object empObj = redisTemplate.opsForValue().get("emp:"+employeeTemp.getId());
        if(empObj==null){
            //要插入缓存
            System.out.println("——————》需要插入缓存");
            redisTemplate.opsForValue().set("emp:"+employeeTemp.getId(),employeeTemp);
        } else {
            //查询数据库
            System.out.println("——————》不需要插入缓存");
        }
        System.out.println("——————》需要插入数据库");
        empMapper.insert02(employeeTemp);

    }

    @Override
    public void update01(EmployeeTemp employeeTemp) {
        Object empObj = redisTemplate.opsForValue().get("emp:"+employeeTemp.getId());
        if(empObj==null){
            //要插入缓存
            System.out.println("——————》需要插入缓存");
            redisTemplate.opsForValue().set("emp:"+employeeTemp.getId(),employeeTemp);
        } else {
            //查询数据库
            System.out.println("——————》需要更新缓存");
            redisTemplate.opsForValue().set("emp:"+employeeTemp.getId(),employeeTemp);
        }
        System.out.println("——————》需要更新数据库");
        empMapper.update02(employeeTemp);

    }

    @Override
    public void delete01(int id) {
        Object empObj = redisTemplate.opsForValue().get("emp:"+id);
        if(empObj==null){
            System.out.println("——————》不用删除缓存");
        } else {
            System.out.println("——————》删除缓存");
            redisTemplate.delete("emp:"+id);
        }
        System.out.println("——————》删除数据库");
        empMapper.deleteEmpById(id);
    }

    @Override
    public Object findEmpById01(int id) {
        //先从缓存中获取数据,如果有就直接返回
        //如果缓存里没有数据,则查询mysql,并将数据设置到缓存中去
        Object empObj = redisTemplate.opsForValue().get("emp:"+id);
        if(empObj==null){
            //查询数据库
            System.out.println("——————》查询数据库");
            EmployeeTemp employee = empMapper.findEmpById02(id);
            System.out.println(employee);
            redisTemplate.opsForValue().set("emp:"+id,employee);
            return employee;
        } else {
            System.out.println("——————》查询缓存");
        }
        return empObj;
    }

}

(5)创建控制层

@RestController
public class RedisController {

    //springboot会根据引入的依赖在ioc中自动的创建这些bean,所以可以直接引用
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private EmployeeServiceImpl employeeService;


    /*第一部分:测试redisTemplate的方法,直接操作redis的数据*/
    // http://localhost:8080/redis/get/name
    @GetMapping("/redis/get/{key}")
    public Object get(@PathVariable("key") String key) {
        return redisTemplate.opsForValue().get(key);
    }

    // http://localhost:8080/redis/set/name/zhangsan
    @PostMapping("/redis/set/{key}/{value}")
    public Object set(
            @PathVariable("key") String key,
            @PathVariable("value") String value) {
        redisTemplate.opsForValue().set(key,value);
        return "set success";
    }

    /*第二部分:测试不用注解版本的redis加数据库的增删改查*/
    // http://localhost:8080/redis/insertEmp01/13/daqiao
    @PostMapping("/redis/insertEmp01/{id}/{name}")
    public Object insertEmp01(
            @PathVariable("id") int id,
            @PathVariable("name") String name) {

        employeeService.insert01(new EmployeeTemp(id,name));
        return "set success";
    }

    // http://localhost:8080/redis/deleteEmp01/14
    @PostMapping("/redis/deleteEmp01/{id}")
    public Object deleteEmp(@PathVariable("id") int id) {
        employeeService.delete01(id);
        return "delete success";
    }

    // http://localhost:8080/redis/findEmpById01/12
    @PostMapping("/redis/findEmpById01/{id}")
    public Object findEmpById01(@PathVariable("id") int id){
        Object employee = employeeService.findEmpById01(id);
        return employee;
    }

    //http://localhost:8080/redis/updateEmp01/2/1111
    @PostMapping("/redis/updateEmp01/{id}/{name}")
    public void updateEmp01(@PathVariable("id") int id,@PathVariable("name") String name) {
        EmployeeTemp employee = new EmployeeTemp(id,name);
        employeeService.update01(employee);
    }
}

根据链接分别测试增删改查的效果

【三】分析序列化配置类

在没有对序列化进行处理之前,存到redis里的信息都是乱码的,要想显示成可读的文字,需要进行序列化处理

//配置 Redis, 这个配置的作用主要是使得保存在 redis 里的key和value转换为如图所示的具有可读性的字符串,否则会是乱码,很不便于观察。
@Configuration
//Redis 缓存配置类
public class RedisConfig extends CachingConfigurerSupport {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
        // 创建 RedisTemplate 对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // 设置连接工厂
        template.setConnectionFactory(connectionFactory);
        // 创建 JSON 序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // 设置 key 的序列化
        template.setKeySerializer(RedisSerializer.string());
        template.setHashKeySerializer(RedisSerializer.string());
        // 设置 value 的序列化
        template.setValueSerializer(jsonRedisSerializer);
        template.setHashValueSerializer(jsonRedisSerializer);
        // 返回
        return template;
    }
}

【四】在不使用注解的情况实现redis和mysql的增删改查

【五】多线程测试redis并发问题

想要实现的效果就是第一次查询数据的时候是从数据库查询,但是以后的查询都从缓存里查询,在没有上锁的情况,很多数据还没有来得及存到缓存,其他线程就从数据库取数据了。
在控制层加上多线程

// http://localhost:8080/redis/findEmpByIdThread/12
@PostMapping("/redis/findEmpByIdThread/{id}")
public Object findEmpByIdThread(@PathVariable("id") int id){
    ExecutorService es = Executors.newFixedThreadPool(200);
    for (int i=0;i<500;i++) {
        es.submit(new Runnable() {
            @Override
            public void run() {
                employeeService.findEmpByIdThread(id);
            }
        });
    }
    Object employee = employeeService.findEmpByIdThread(id);
    return employee;
}

在业务层加上synchronize锁解决并发问题

@Override
public Object findEmpByIdThread(int id) {
    //先从缓存中获取数据,如果有就直接返回
    //如果缓存里没有数据,则查询mysql,并将数据设置到缓存中去
    Object empObj = redisTemplate.opsForValue().get("emp:"+id);
    if(empObj==null){
        synchronized (this.getClass()) {
            empObj = redisTemplate.opsForValue().get("emp:"+id);
            if(empObj==null){
                //查询数据库
                System.out.println("——————》查询数据库");
                EmployeeTemp employee = empMapper.findEmpById02(id);
                System.out.println(employee);
                redisTemplate.opsForValue().set("emp:"+id,employee);
                return employee;
            } else {
                System.out.println("——————》查询缓存(同步代码块)");
                return empObj;
            }
        }

    } else {
        System.out.println("——————》查询缓存");
    }
    return empObj;
}

【六】使用Java注解实现redis的增删改查

1-重点注意实体类要实现序列化接口才可以,不需要无参构造器

public class Employee implements Serializable {
    private int id;
    private String name;

    public Employee(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

2-在service层改成注解的形式

    //增加数据
    @Override
    @Cacheable(value = "employee",key = "'employee-'+#id")
    public Employee findEmpById02(int id) {
        Employee employee = empMapper.findEmpById(id);
        return employee;
    }

    @Override
    @CachePut(value = "employee",key = "'employee-'+#employee.getId()")
    public Employee insert02(Employee employee) {
        empMapper.insert01(employee);
        return employee;
    }

    @Override
    @CacheEvict(value = "employee",key = "'employee-'+#id")
    public void delete02(int id) {
        empMapper.deleteEmpById(id);
    }

    @Override
    @CachePut(value = "employee",key = "'employee-'+#employee.getId()")
    public Employee update02(Employee employee) {
        empMapper.update(employee);
        return employee;
    }

    @Override
    @Cacheable(value = "employee",key = "'employee-'+#id")
    public List<Employee> findAll02() {
        List<Employee> employeeList = empMapper.findAll();
        // JSONObject jsonObject = JSONObject.
        return empMapper.findAll();
    }

    @Override
    @CacheEvict(allEntries=true)
    public void deleteAll02() {
        empMapper.deleteAll();
    }
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值