The main objective of this project is to optimize performance by integrating Redis Caching into this project.This is achieved through the creation of a custom annotation called @LogExecutionTime, which is designed to work seamlessly with Spring AOP. By annotating methods with @LogExecutionTime, we can accurately measure the execution time of these methods both before and after utilizing Redis Cache to fetch data from the database. This provides valuable insights into the efficiency gains achieved through caching, allowing us to assess the impact of caching on method execution times.
- SpringBoot
- SpringAop
- Redis
- MySQL
- Controller
- Model
- Aspect
- Service
- Repository
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
# Redis Config
spring.cache.type=redis
spring.redis.host=localhost
spring.redis.port=6379
# Database Config
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3312/db
spring.datasource.username=db
spring.datasource.password=nFLhPPKOnkW1FA1e
spring.jpa.show-sql=true
✏️ Create entity called product. Since Redis is an in-memeory database, we need to transform our object into stream of bytes for storing as well as the other way around for retrieving data. So we nedd to serialize/deserialize by implements the Serializable class.
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String name;
private String code;
private int quantity;
private double price;
}
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
}
✏️ @EnableCaching annotation that's will trigger inspects every Spring bean for the presence of caching annotations on methods.
@SpringBootApplication
@EnableCaching
public class SpringDataWithRedisApplication {
public static void main(String[] args) {
SpringApplication.run(SpringDataWithRedisApplication.class, args);
}
}
✏️ @Cacheable is used to bring data from database and storing it in the cache. In future, the method retrives data from the cache value directly.The value attribute establishes a cache with a specific name and the key is a unique identifier that represents a specific piece of cached data. Accordingly, the method result is stored in the "product" cache, where respective "id" of product as the unique key.
@Cacheable(key = "#id", value = "product")
public Product getById(long id) {
return repository.findById(id).get();
}
✏️ @Caching is used for multiple nested caching on the same method. Inside @CacheEvict the allEntries attribute allow us to remove all given cache by make it as true with another cache name then we going to update data in the cache using @CachePut.
@Caching(evict = { @CacheEvict(value = "evictProduct", allEntries = true) }, put = {
@CachePut(key = "#id", value = "product") })
public Product update(Product model, long id) {
var product = repository.findById(id).get();
product.setName(model.getName());
product.setCode(model.getCode());
product.setPrice(model.getPrice());
product.setQuantity(model.getQuantity());
repository.save(model);
return product;
}
@CacheEvict(key = "#id", cacheNames = "product")
public void deleteById(long id) {
repository.deleteById(id);
}