SpringBoot高级 -- SpringBoot与缓存

一、几个重要概念&缓存注解

 

二、搭建基本环境

1、SpringBoot整合Mybatis操作数据库

(1)配置数据源信息

characterEncoding=utf-8&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/spring_cache?characterEncoding=utf-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=password

# 开启驼峰命名
mybatis.configuration.map-underscore-to-camel-case=true 

logging.level.com.dhu.cache.mapper=debug

(2)使用@MapperScan 指定需要扫描的mapper接口所在的包

@SpringBootApplication
@MapperScan(basePackages = "com.dhu.cache.mapper")
@EnableCaching
public class Springboot01CacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springboot01CacheApplication.class, args);
    }
}

(3)

public interface EmployeeMapper {

    @Select("SELECT * FROM employee WHERE id = #{id}")
    Employee getEmpById(Integer id);

    @Update("UPDATE employee SET lastName = #{lastName},email = #{email},gender = #{gender},d_id = #{dId} WHERE id = #{id}")
    void updataEmp(Employee employee);

    @Delete("DELETE FROM employee WHERE id = #{id}")
    void deleteEmp(Integer id);

    @Insert("INSERT INTO employee(lastName,email,gender,d_id) VALUES(#{lastName},#{email},#{gender},#{dId})")
    @Options(useGeneratedKeys = true,keyProperty = "id", keyColumn = "id")
    void insertEmp(Employee employee);
}

(4)

@Controller
public class EmployeeController {
    @Autowired
    private EmployeeService employeeService;

    @GetMapping("/emp/{id}")
    @ResponseBody
    public Employee getEmp(@PathVariable("id") Integer id){
        Employee emp = employeeService.getEmp(id);
        return emp;
    }
}

 

三、快速使用缓存

1、开启基于注解的缓存 @EnableCaching

@SpringBootApplication
@MapperScan(basePackages = "com.dhu.cache.mapper")
@EnableCaching
public class Springboot01CacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springboot01CacheApplication.class, args);
    }
}

2、标注缓存注解即可 

使用@Cacheable

@Service
@Slf4j
@Transactional
public class EmployeeService {
    @Resource
    private EmployeeMapper employeeMapper;

    /**
     * @Cacheable :将方法的运行结果进行缓存;以后再需要查询相同的数据,直接从缓存获取,不用调用方法
     *
     * CacheManager:用来管理多个Cache组件,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有唯一名字
     *  几个属性:
     *      value/cacheNames:指定缓存组件的名字
     *      key:指定缓存数据时使用的key (缓存使用hashmap)。默认是使用方法参数的值,例如:1-方法的返回值
     *          可以编写SPEL
     *      keyGenerator: key的生成器;可以自己指定key的生成器的组件id
     *          key/keyGenerator: 二选一使用
     *      cacheManager:指定缓存管理器
     *      condition:指定符合条件的情况下才缓存
     *      unless: 否定缓存。当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断
     * @param id
     * @return
     */
    @Cacheable(cacheNames = {"emp"},key = "#id",condition = "#id>0",unless = "#result==null")  //#id 的作用是:取出参数id的值,把它作为key
    public Employee getEmp(Integer id) {
        System.out.println("查询" + id + "号员工...");
        Employee emp = employeeMapper.getEmpById(id);
        return emp;
    }
}

 

四、缓存的使用

1、EmployeeService

@Cacheable

查询的缓存正常

@Service
@Slf4j
@Transactional
public class EmployeeService {
    @Resource
    private EmployeeMapper employeeMapper;

    /**
     * @Cacheable :将方法的运行结果进行缓存;以后再需要查询相同的数据,直接从缓存获取,不用调用方法
     *
     * CacheManager:用来管理多个Cache组件,对缓存的真正CRUD操作在Cache组件中,每一个缓存组件有唯一名字
     *  几个属性:
     *      value/cacheNames:指定缓存组件的名字
     *      key:指定缓存数据时使用的key (缓存使用hashmap)。默认是使用方法参数的值,例如:1-方法的返回值
     *          可以编写SPEL
     *      keyGenerator: key的生成器;可以自己指定key的生成器的组件id
     *          key/keyGenerator: 二选一使用
     *      cacheManager:指定缓存管理器
     *      condition:指定符合条件的情况下才缓存
     *      unless: 否定缓存。当unless指定的条件为true,方法的返回值就不会被缓存;可以获取到结果进行判断
     *
     * 缓存工作原理:
     *      1、自动配置类 : (缓存自动配置类) CacheAutoConfiguration
     *      2、哪个配置类默认生效
     *  运行流程:
     *      1、@Cacheable标注的方法在执行之前,先来检查缓存中有没有这个数据,默认按照参数的值作为key去查询缓存,如果没有就运行新的方法,
     * 并将结果放入缓存;以后再来调用就可以直接使用缓存中的数据
     * @param id
     * @return
     */
    @Cacheable(cacheNames = {"emp"},key = "#root.methodName + '[' + #id + ']'",condition = "#id>0",unless = "#result==null")  //#id 的作用是:取出参数id的值,把它作为key
    public Employee getEmp(Integer id) {
        System.out.println("查询" + id + "号员工...");
        Employee emp = employeeMapper.getEmpById(id);
        return emp;
    }

2、Controller

@Controller
public class EmployeeController {
    @Autowired
    private EmployeeService employeeService;

    @GetMapping("/emp/{id}")
    @ResponseBody
    public Employee getEmp(@PathVariable("id") Integer id){
        Employee emp = employeeService.getEmp(id);
        return emp;
    }

3、@CachePut

    /**
     * @CachePut:既调用方法,又更新缓存数据
     *      也就是修改了数据库的某个数据,同时更新缓存
     *  运行时机:
     *      1、先调用目标方法
     *      2、将目标方法的结果缓存起来
     *  测试:
     *      1、查询1号员工;查到的结果会放在缓存中
     *      2、以后查询还是之前的结果
     *      3、更新1号员工
     *      4、再次查询1号员工?
     *              应该是更新后的员工;可是为什么查询出来的是没更新前的?
     */
    @CachePut(value = "{emp")
    public Employee updateEmp(Employee employee){
        System.out.println("update --- " + employee);
        employeeMapper.updataEmp(employee);
        return employee;
    }

4、使用更新操作与缓存

    @ResponseBody
    @GetMapping("/emp")
    public Employee update(Employee employee){
        employeeService.updateEmp(employee);
        return employee;
    }

5、存在问题 

 

6、解决

    /**
     * @CachePut:既调用方法,又更新缓存数据
     *      也就是修改了数据库的某个数据,同时更新缓存
     *  运行时机:
     *      1、先调用目标方法
     *      2、将目标方法的结果缓存起来
     *  测试:
     *      1、查询1号员工;查到的结果会放在缓存中
     *          key:1  value:lastName:李四
     *      2、以后查询还是之前的结果
     *      3、更新1号员工:
     *          将方法的返回值也放进缓存
     *          key:employee(默认是使用方法参数的值)  value:返回的employee对象
     *      4、再次查询1号员工?
     *              应该是更新后的员工;
     *              可是为什么查询出来的是没更新前的?【1号员工没有在缓存中更新】
     *           解决方法:
     *              使用key = "#employee.id":使用传入员工参数对象的id;
     *              或者key = "#result.id"
     */
    @CachePut(value = {"emp"},key = "#employee.id")
    public Employee updateEmp(Employee employee){
        System.out.println("update --- " + employee);
        employeeMapper.updataEmp(employee);
        return employee;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值