【redis-01】redis整合springboot实现简单的增删改查
(1)基本的环境配置 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
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
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.jpa.show-sql=true
logging.level.com.allen.hello_redis.Mapper:debug
(2)基本的代码准备 1-准备数据库和数据表 2-创建实体类
public class EmployeeTemp {
private int id;
private String name;
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;
@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) {
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 {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private EmployeeServiceImpl employeeService;
@GetMapping("/redis/get/{key}")
public Object get(@PathVariable("key") String key) {
return redisTemplate.opsForValue().get(key);
}
@PostMapping("/redis/set/{key}/{value}")
public Object set(
@PathVariable("key") String key,
@PathVariable("value") String value) {
redisTemplate.opsForValue().set(key,value);
return "set success";
}
@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";
}
@PostMapping("/redis/deleteEmp01/{id}")
public Object deleteEmp(@PathVariable("id") int id) {
employeeService.delete01(id);
return "delete success";
}
@PostMapping("/redis/findEmpById01/{id}")
public Object findEmpById01(@PathVariable("id") int id){
Object employee = employeeService.findEmpById01(id);
return employee;
}
@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);
}
}
根据链接分别测试增删改查的效果
(3)分析序列化配置类 在没有对序列化进行处理之前,存到redis里的信息都是乱码的,要想显示成可读的文字,需要进行序列化处理
@Configuration
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
template.setValueSerializer(jsonRedisSerializer);
template.setHashValueSerializer(jsonRedisSerializer);
return template;
}
}
(4)在不使用注解的情况实现redis和mysql的增删改查
(5)多线程测试redis并发问题 想要实现的效果就是第一次查询数据的时候是从数据库查询,但是以后的查询都从缓存里查询,在没有上锁的情况,很多数据还没有来得及存到缓存,其他线程就从数据库取数据了。 在控制层加上多线程
@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) {
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;
}
(6)使用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();
return empMapper.findAll();
}
@Override
@CacheEvict(allEntries=true)
public void deleteAll02() {
empMapper.deleteAll();
}
|