使用的是mybatis用来操作数据库
基本概念
在计算机存储系统的层次结构中,介于中央处理器和主存储器之间的高速小容量存储器。它和主存储器一起构成一级的存储器。高速缓冲存储器和主存储器之间信息的调度和传送是由硬件自动进行的。
某些机器甚至有二级三级缓存,每级缓存比前一级缓存速度慢且容量大。
组成结构
高速缓冲存储器是存在于主存与CPU之间的一级存储器, 由静态存储芯片(SRAM)组成,容量比较小但速度比主存高得多, 接近于CPU的速度。
主要由三大部分组成:
Cache存储体:存放由主存调入的指令与数据块。
地址转换部件:建立目录表以实现主存地址到缓存地址的转换。
替换部件:在缓存已满时按一定策略进行数据块替换,并修改地址转换部件。
映射方式
在cache中,地址映射是指把主存地址空间映射到cache地址空间,也就是把存放在主存中的数据按照某种规则装入到cache中。共有直接映射,全相联映射,组相联映射三种映射方式。
启动类
/**
* 一 搭建基本环境
* 1.导入数据库文件,创建出数据库
* 2.创建javabean 封装数据
*3.整合mybatis 操作数据库
* a.配置数据源信息
* b.使用注解版的mybaits
* A.指定@MapperScan指定扫描的mapper接口所在的包 在启动类上加上 @MapperScan("springbootcatch.springbootcatch.mapper")
*
* 二 快速体验缓存
* 步骤
* 1.开启基于注解的缓存
* 2.标注缓存注解即可 在启动类上面加上@EnableCaching
* @Cacheable 表示这个方法是可缓存的
* @CacheEvict 清空缓存
* @CachePut 保证方法被调用又希望结果被缓存
*
* */
@MapperScan("springbootcatch.springbootcatch.mapper")
@SpringBootApplication
@EnableCaching //开启基于注解的缓存
public class SpringbootcatchApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootcatchApplication.class, args);
}
}
测试类(对应数据库)
public class Employee {
int id;
String lastName;
String email;
int gender;
int aid;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
public int getAid() {
return aid;
}
public void setAid(int aid) {
this.aid = aid;
}
public Employee(String lastName, String email, int gender, int aid) {
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.aid = aid;
}
public Employee(int id, String lastName, String email, int gender, int aid) {
this.id = id;
this.lastName = lastName;
this.email = email;
this.gender = gender;
this.aid = aid;
}
public Employee() {
}
}
controller
@RestController
public class EmployeeController {
@Autowired
EmployeeService employeeService;
@GetMapping("/getemp/{id}")
public Employee getEmployee(@PathVariable("id") int id) {
return employeeService.getEmp(id);
}
@GetMapping("/getempcache/{id}")
public Employee getEmployeecache(@PathVariable("id") int id) {
return employeeService.getEmp(id);
}
@GetMapping("/emp")
public Employee update(Employee employee) {
System.out.println("update emp:"+employee);
return employeeService.updateEmployee(employee);
}
@GetMapping("/delemp/{id}")
public String deleteEMP(@PathVariable("id") int id){
employeeService.deleteEmp(id);
return "success";
}
@GetMapping("/getmpByLastName/{lastName}")
public Employee getmpByLastName(@PathVariable("lastName")String lastName){
return employeeService.getEmpByLastName(lastName);
}
}
mapper
@Mapper
public interface EmploeeMapper {
@Select("select * from employee where id = #{id}")
public Employee getEmployeeById(Integer id);
@Update("update employee set lastName=#{lastName},email=#{email},gender=#{gender},d_id=#{aid} where id = #{id}")
public void updateEmployee(Employee employee);
@Delete("delete from employee where id = #{id}")
public void deleteEmployee(Integer id);
@Insert("insert into employee(lastName,email,gender,d_id) values(#{lastName},#{email},#{gender},#{aid}) ")
public void insertUser(Employee employee);
@Select("select * from employee where lastName = #{lastName}")
Employee getEmployeeByLastName(String lastName);
}
service
@Service
public class EmployeeService {
@Autowired
EmploeeMapper emploeeMapper;
/**
* 将方法的运行结果进行缓存,以后要相同的数据,直接从缓存中获取,不用调用方法
* cacheManager 管理多个cache组件的,对缓存的真正CRUD操作早cache组件,每一个缓存组件有自己唯一一个名字
*
* @param id
* @return
* @Cacheable的几个属性 cachenames/value :指定缓存的名字
* key:缓存数据时使用的key (缓存用的是key value模式缓存) 可以用他来指定.默认是使用方法参数的值 1-方法的返回值
* 编写SpEl #id;参数id的值 #a0 #p0 #root.args[0]
* keyGenerator:key 的生成器:可以自己指定key的生成器的组件id
* keyGenerator/key 二选一使用
* CacheManager:指定缓存管理器: 或者cacheResolver 指定获取解析器
* condition: 指定符合条件的情况下才缓存
* unless: 否定缓存,当unless指定的条件为true,方法的返回值就不会被缓存,可以获取到结果进行判断
* sync: 缓存是否使用异步模式
* <p>
* , key = "#id",condition = "#id>0",unless = "#result==null"
* <p>
* 原理:
* 1.自动配置类: CacheAutoConfiguration
* 2.缓存的配置类
* org.springframework.boot.autoconfigure.cache.GenericacheConfiguration
* ****
* ****
* 3.那个配置类默认生效
* 4.给容器中注册了一个缓存管理器
* 5.可以获取和创建concurrendMapCache类型的缓存组件,它的作用将数据保存在concurrentMap中
* <p>
* <p>
* 运行流程:
* @Cacheable 1.方法运行之前, 先去查询Cache(缓存组件), 按照cacheNames指定的名字获取 (cacheManager先获取相应的缓存) 第一次获取缓存会自动创建
* 2.去Cache中查找缓存的内容,使用一个key,默认是方法的参数: key是按照某种策略生成的,默认是使用keyGenerator生成的
* 3.没有查到缓存就调用目标方法
* 4.将目标方法的返回结果,放进缓存中
* @Cacheable: 标注的方法执行之前先来检查缓存中有没有这个数据, 默认按照参数的值作为key去查询缓存, 如果没有就运行方法把结果放入缓存
* 核心:
* 1).使用CacheManager按照名字得到Cache组件
* 2).key使用keyGenerator生成的,默认是SimpleKeyGenerator
*/
@Cacheable(cacheNames = {"getempcache"}, key = "#id")
// #id 是指取出id的值作为缓存的key condition 满足条件才缓存 unless 如果结果为空则不缓存
public Employee getEmp(int id) {
System.out.println("查询 id 为" + id + "的记录并缓存");
return emploeeMapper.getEmployeeById(id);
}
/**
* @CachePut 既调用方法, 又更新缓存数据
* 修改了某个数据库的数据,同时更新缓存
* 运行时机:
* 1.先调用目标方法
* 2.将目标方法的结果缓存起来
* 同步更新缓存 只是取缓存的key和放缓存的key要一样
*/
@CachePut(cacheNames = {"getempcache"}, key = "#employee.id")
//让缓存更新 要指定cachename 指定缓存的key的id 需要和上面查询的id一样 不然这边更新了 上面缓存的没有更新
public Employee updateEmployee(Employee employee) {
emploeeMapper.updateEmployee(employee); //更新员工操作
return employee;
}
/**
* @CacheEvict:缓存清除 key:指定要清除那个key
* allEntries = true 删除缓存中的所有数据
* beforeInvocation = false 是否在方法之前执行, 默认是在方法之后 执行
*/
@CacheEvict(cacheNames = {"getempcache"}, key = "#id")
public void deleteEmp(Integer id) {
System.out.println("deleteEmp:" + id);
// emploeeMapper.deleteEmployee(id);
}
/**
* @param lastName
* @return
* @Caching 是
* Cacheable[] cacheable() default {};
* <p>
* CachePut[] put() default {};
* <p>
* CacheEvict[] evict() default {};
* <p>
* 这三个注解的集合 用于指定多规则的复杂缓存
*/
@Caching(
cacheable = {
@Cacheable(cacheNames = {"getempcache"}, key = "#lastName")
},
put = {
@CachePut(cacheNames = {"getempcache"}, key = "#result.id"),
@CachePut(cacheNames = {"getempcache"}, key = "#result.email")
}
)
public Employee getEmpByLastName(String lastName) {
return emploeeMapper.getEmployeeByLastName(lastName);
}
}
第二种
/**
* 如果一个类都是需要缓存的 那就可以用@CacheConfig 来指定这个类
* 存取缓存的公共配置
* 写了这个的话下面的
* 公共的东西就不用写了
*
*
* cacheNames = {"getempcache"},
*/
@Service
@CacheConfig(cacheNames = "getempcache")
public class EmployeeServiceTwo {
@Autowired
EmploeeMapper emploeeMapper;
/**
* @CachePut 既调用方法, 又更新缓存数据
* 修改了某个数据库的数据,同时更新缓存
* 运行时机:
* 1.先调用目标方法
* 2.将目标方法的结果缓存起来
* 同步更新缓存 只是取缓存的key和放缓存的key要一样
*/
@CachePut( key = "#employee.id")
//让缓存更新 要指定cachename 指定缓存的key的id 需要和上面查询的id一样 不然这边更新了 上面缓存的没有更新
public Employee updateEmployee(Employee employee) {
emploeeMapper.updateEmployee(employee); //更新员工操作
return employee;
}
/**
* @CacheEvict:缓存清除 key:指定要清除那个key
* allEntries = true 删除缓存中的所有数据
* beforeInvocation = false 是否在方法之前执行, 默认是在方法之后 执行
*/
@CacheEvict( key = "#id")
public void deleteEmp(Integer id) {
System.out.println("deleteEmp:" + id);
// emploeeMapper.deleteEmployee(id);
}
}