前言
我們都知道,一個(gè)程序的瓶頸通常都在數(shù)據(jù)庫(kù),很多場(chǎng)景需要獲取相同的數(shù)據(jù)。比如網(wǎng)站頁(yè)面數(shù)據(jù)等,需要一次次的請(qǐng)求數(shù)據(jù)庫(kù),導(dǎo)致大部分時(shí)間都浪費(fèi)在數(shù)據(jù)庫(kù)查詢(xún)和方法調(diào)用上,這時(shí)就可以利用到緩存來(lái)緩解這個(gè)問(wèn)題。
簡(jiǎn)介
本文來(lái)介紹SpringBoot來(lái)簡(jiǎn)單整合緩存,使用SpringBoot+JPA+mysql來(lái)進(jìn)行數(shù)據(jù)庫(kù)操作。整合JPA的文章,具體可以參考 傳送門(mén)。
新建項(xiàng)目
創(chuàng)建一個(gè)項(xiàng)目,pom文件中加入spring-boot-starter-cache依賴(lài),完整pom如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dalaoyang</groupId>
<artifactId>springboot_cache</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>springboot_cache</name>
<description>springboot_cache</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置文件如下,和整合JPA一樣,沒(méi)有做任何修改:
##端口號(hào)
server.port=8888
##數(shù)據(jù)庫(kù)配置
##數(shù)據(jù)庫(kù)地址
spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useSSL=false
##數(shù)據(jù)庫(kù)用戶(hù)名
spring.datasource.username=root
##數(shù)據(jù)庫(kù)密碼
spring.datasource.password=root
##數(shù)據(jù)庫(kù)驅(qū)動(dòng)
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
##validate 加載hibernate時(shí),驗(yàn)證創(chuàng)建數(shù)據(jù)庫(kù)表結(jié)構(gòu)
##create 每次加載hibernate,重新創(chuàng)建數(shù)據(jù)庫(kù)表結(jié)構(gòu),這就是導(dǎo)致數(shù)據(jù)庫(kù)表數(shù)據(jù)丟失的原因。
##create-drop 加載hibernate時(shí)創(chuàng)建,退出是刪除表結(jié)構(gòu)
##update 加載hibernate自動(dòng)更新數(shù)據(jù)庫(kù)結(jié)構(gòu)
##validate 啟動(dòng)時(shí)驗(yàn)證表的結(jié)構(gòu),不會(huì)創(chuàng)建表
##none 啟動(dòng)時(shí)不做任何操作
spring.jpa.hibernate.ddl-auto=update
##控制臺(tái)打印sql
spring.jpa.show-sql=true
實(shí)體類(lèi)代碼如下:
package com.dalaoyang.entity;
import javax.persistence.*;
/**
* @author dalaoyang
* @Description
* @project springboot_learn
* @package com.dalaoyang.entity
* @email yangyang@dalaoyang.cn
* @date 2018/5/28
*/
@Entity
public class House {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private int id;
@Column(length = 10)
private String houseName;
private String houseSize;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getHouseName() {
return houseName;
}
public void setHouseName(String houseName) {
this.houseName = houseName;
}
public String getHouseSize() {
return houseSize;
}
public void setHouseSize(String houseSize) {
this.houseSize = houseSize;
}
public House(String houseName, String houseSize) {
this.houseName = houseName;
this.houseSize = houseSize;
}
public House(int id,String houseName, String houseSize) {
this.id = id;
this.houseName = houseName;
this.houseSize = houseSize;
}
public House() {
}
}
Repository如下:
package com.dalaoyang.repository;
import com.dalaoyang.entity.House;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author dalaoyang
* @Description
* @project springboot_learn
* @package com.dalaoyang.repository
* @email yangyang@dalaoyang.cn
* @date 2018/5/28
*/
public interface HouseRepository extends JpaRepository<House,Integer> {
}
啟動(dòng)類(lèi)上加入@EnableCaching開(kāi)啟緩存,完整代碼如下:
package com.dalaoyang;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
//開(kāi)啟緩存
@EnableCaching
public class SpringbootCacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootCacheApplication.class, args);
}
}
還是和以往一樣,使用Controller做測(cè)試,先展示一下代碼:
package com.dalaoyang.controller;
import com.dalaoyang.entity.House;
import com.dalaoyang.repository.HouseRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author dalaoyang
* @Description
* @project springboot_learn
* @package com.dalaoyang.controller
* @email yangyang@dalaoyang.cn
* @date 2018/5/28
*/
@RestController
public class HouseController {
@Autowired
private HouseRepository houseRepository;
//http://localhost:8888/saveHouse?id=1&houseName=別墅&houseSize=1220平方米
@GetMapping("/saveHouse")
@CachePut(value = "house", key = "#id")
public House saveHouse(Integer id,String houseName,String houseSize){
House house = new House(id,houseName, houseSize);
houseRepository.save(house);
return house;
}
//http://localhost:8888/queryHouse?id=1
@GetMapping("/queryHouse")
@Cacheable(value = "house", key = "#id")
public House queryHouse(Integer id){
House house = houseRepository.findOne(id);
return house;
}
//http://localhost:8888/deleteHouse?id=1
@GetMapping("/deleteHouse")
@CacheEvict(value = "house", key = "#id")
public String deleteHouse(Integer id){
houseRepository.delete(id);
return "success";
}
//http://localhost:8888/deleteCache
@GetMapping("/deleteCache")
@CacheEvict(value = "house", allEntries = true)
public void deleteCache() {
}
}
解釋測(cè)試方法
1.saveHouse方法
方法中使用到了@CachePut注解,這個(gè)注解直接將返回值放入緩存中,通常用于保存和修改方法中
2.queryHouse方法
方法中使用到了@Cacheable注解,這個(gè)注解在執(zhí)行前先查看緩存中是不是已經(jīng)存在了,如果存在,直接返回。如果不存在,將方法的返回值放入緩存。
3.deleteHouse方法
方法中使用到了@CacheEvict注解,這個(gè)注解在執(zhí)行方法執(zhí)行成功后會(huì)從緩存中移除
4.deleteCache方法
這個(gè)方法的也是使用的@CacheEvict注解,不同的是使用了allEntries熟悉,默認(rèn)為false,true的時(shí)候移除所有緩存。
測(cè)試
1.首先訪問(wèn)http://localhost:8888/saveHouse?id=1&houseName=別墅&houseSize=1220平方米,然后查看數(shù)據(jù)庫(kù)和控制臺(tái),如下圖:
2.訪問(wèn)http://localhost:8888/queryHouse?id=1,查看頁(yè)面數(shù)據(jù)和控制臺(tái)。因?yàn)樵O(shè)置了打印執(zhí)行jpa查詢(xún)的話打印sql,看下圖控制臺(tái)沒(méi)有打印,證明在保存的時(shí)候@CachePut注解已經(jīng)將其放入了緩存中。
3.調(diào)用清空緩存方法http://localhost:8888/deleteCache然后在次訪問(wèn)查詢(xún)方法http://localhost:8888/queryHouse?id=1,查看控制臺(tái)如下,可以到清空緩存后,在訪問(wèn)就需要查詢(xún)數(shù)據(jù)庫(kù)。
4.調(diào)用刪除方法http://localhost:8888/deleteHouse?id=1,然后在方法查詢(xún)方法http://localhost:8888/queryHouse?id=1,查看控制臺(tái)如下,可以到刪除緩存后,在訪問(wèn)也查詢(xún)了數(shù)據(jù)庫(kù)。
源碼下載 :大老楊碼云