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

本文详细介绍了如何在SpringBoot项目中整合Redis,包括环境配置、实体类、Mapper与Service的实现,以及序列化处理和多线程并发测试。重点展示了Java注解在Redis操作中的应用以及解决并发问题的方法。
摘要由CSDN通过智能技术生成

【一】基本的环境配置

(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();
    }
好的,以下是使用SpringBoot整合Redis实现简单增删改查操作的代码示例: 1.首先,在pom.xml文件中添加RedisSpring Data Redis的依赖: ``` <!-- Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2.在application.properties文件中配置Redis的连接信息: ``` spring.redis.host=localhost # Redis服务器地址 spring.redis.port=6379 # Redis服务器端口 ``` 3.创建一个RedisConfig配置类,用于配置Redis连接池和RedisTemplate: ``` @Configuration public class RedisConfig { @Bean public JedisConnectionFactory jedisConnectionFactory() { JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(); jedisConnectionFactory.setHostName("localhost"); // Redis服务器地址 jedisConnectionFactory.setPort(6379); // Redis服务器端口 return jedisConnectionFactory; } @Bean public RedisTemplate<String, Object> redisTemplate() { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(jedisConnectionFactory()); redisTemplate.setDefaultSerializer(new StringRedisSerializer()); // key的序列化方式 redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class)); // value的序列化方式 return redisTemplate; } @Bean public RedisCacheManager redisCacheManager() { return RedisCacheManager.create(jedisConnectionFactory()); } } ``` 4.创建一个User实体类,用于测试Redis增删改查操作: ``` @Data @NoArgsConstructor @AllArgsConstructor public class User implements Serializable { private static final long serialVersionUID = 1L; private String id; private String name; private Integer age; } ``` 5.创建一个UserController类,用于测试Redis增删改查操作: ``` @RestController @RequestMapping("/user") public class UserController { @Autowired private RedisTemplate<String, Object> redisTemplate; @PostMapping public String add(@RequestBody User user) { redisTemplate.opsForValue().set(user.getId(), user); return "success"; } @GetMapping("/{id}") public User get(@PathVariable String id) { return (User) redisTemplate.opsForValue().get(id); } @PutMapping public String update(@RequestBody User user) { redisTemplate.opsForValue().set(user.getId(), user); return "success"; } @DeleteMapping("/{id}") public String delete(@PathVariable String id) { redisTemplate.delete(id); return "success"; } } ``` 以上就是使用SpringBoot整合Redis实现简单增删改查操作的代码示例,希望能够帮助到你。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值