データキャッシング-Java Spring

同じデータを繰り返し読むと、最適化の問題が生じます。データは変わらないか、めったに変わりません。これらはさまざまな参考書やその他の情報です。 キーによってデータを取得する機能は決定的です。 ここでは、おそらく誰もが理解しています-キャッシュが必要です! 毎回データ検索または計算を実行する必要があるのはなぜですか?



そこで、ここではJava Springでキャッシュを作成する方法を示します。キャッシュはデータベースと密接に関連している可能性が高いため、特定の例を使用してDBMSでキャッシュを作成する方法を説明します。



内容





Springのキャッシュ



その後、すべてがほぼ同じようになります。JavaではさまざまなHasMap、ConcurrentMapなどを使用します。Springでも、この解決策が簡単で便利で効果的です。 ほとんどの場合、これは問題の解決に役立つと思います。 したがって、必要なのは、キャッシュを有効にして関数に注釈を付けることだけです。



キャッシュをアクセス可能にする



@SpringBootApplication @EnableCaching public class DemoCacheAbleApplication { public static void main(String[] args) { SpringApplication.run(DemoCacheAbleApplication.class, args); } }
      
      





キャッシュ機能検索データ



  @Cacheable(cacheNames="person") public Person findCacheByName(String name) { //... }
      
      





注釈はキャッシュの名前を示し、他のパラメーターもあります。 コードは最初に実行され、検索結果がキー(この場合は名前)によってキャッシュに入れられ、以降の呼び出しは実行されなくなり、データがキャッシュから取得されます。



キャッシュを使用した「個人」リポジトリの実装例



 @Component public class PersonRepository { private static final Logger logger = LoggerFactory.getLogger(PersonRepository.class); private List<Person> persons = new ArrayList<>(); public void initPersons(List<Person> persons) { this.persons.addAll(persons); } private Person findByName(String name) { Person person = persons.stream() .filter(p -> p.getName().equals(name)) .findFirst() .orElse(null); return person; } @Cacheable(cacheNames="person") public Person findCacheByName(String name) { logger.info("find person ... " + name); final Person person = findByName(name); return person; } }
      
      





何が起こったのか確認する



 @RunWith(SpringRunner.class) @SpringBootTest public class DemoCacheAbleApplicationTests { private static final Logger logger = LoggerFactory.getLogger(DemoCacheAbleApplicationTests.class); @Autowired private PersonRepository personRepository; @Before public void before() { personRepository.initPersons(Arrays.asList(new Person("", 22), new Person("", 34), new Person("", 41))); } private Person findCacheByName(String name) { logger.info("begin find " + name); final Person person = personRepository.findCacheByName(name); logger.info("find result = " + person.toString()); return person; } @Test public void findByName() { findCacheByName(""); findCacheByName(""); } }
      
      





テストでは2回呼び出します



 @Test public void findByName() { findCacheByName(""); findCacheByName(""); }
      
      





、最初の呼び出し、検索、2回目の結果はキャッシュから既に取得されています。 これはコンソールに表示されます。



画像



便利なことに、既存の機能を個別に最適化できます。 関数に複数の引数がある場合は、キーとして使用するパラメーター名を指定できます。



  @Cacheable(cacheNames="person", key="#name") public Person findByKeyField(String name, Integer age) {
      
      





キーを取得するためのより複雑なスキームがあります。これはドキュメントにあります。



しかし、もちろん、問題はキャッシュ内のデータを更新する方法でしょうか? この目的には2つの注釈があります。



最初は@CachePut







この注釈を持つ関数は常にコードを呼び出し、結果をキャッシュに格納するため、キャッシュを更新できます。



リポジトリーに2つのメソッドを追加します:削除と個人の追加



  public boolean delete(String name) { final Person person = findByName(name); return persons.remove(person); } public boolean add(Person person) { return persons.add(person); }
      
      





Personの検索、削除、追加、再検索を行いますが、以前と同様に、「findByNameAndPut」を呼び出すまでキャッシュから同じ顔を取得します



  @CachePut(cacheNames="person") public Person findByNameAndPut(String name) { logger.info("findByName and put person ... " + name); final Person person = findByName(name); logger.info("put in cache person " + person); return person; }
      
      





テスト



  @Test public void findCacheByNameAndPut() { Person person = findCacheByName(""); logger.info("delete " + person); personRepository.delete(""); findCacheByName(""); logger.info("add new person"); person = new Person("", 35); personRepository.add(person); findCacheByName(""); logger.info("put new"); personRepository.findByNameAndPut(""); findCacheByName(""); }
      
      





画像



別の注釈は@CacheEvict







キャッシュストレージにアクセスするだけでなく、削除することもできます。 このプロセスは、キャッシュから古いデータや未使用のデータを削除するのに役立ちます。



デフォルトでは、Springはキャッシュに-ConcurrentMapCacheを使用します。キャッシュを整理するための独自の優れたクラスがある場合、CacheManagerでこれを指定することができます。



 @SpringBootApplication @EnableCaching public class DemoCacheAbleApplication { public static void main(String[] args) { SpringApplication.run(DemoCacheAbleApplication.class, args); } @Bean public CacheManager cacheManager() { SimpleCacheManager cacheManager = new SimpleCacheManager(); cacheManager.setCaches(Arrays.asList( new ConcurrentMapCache("person"), new ConcurrentMapCache("addresses"))); return cacheManager; } }
      
      





キャッシュの名前もそこに示されていますが、いくつかある場合があります。 xml構成では、これは次のように示されます。



Spring configuration.xml
 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> <cache:annotation-driven/> <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager"> <property name="caches"> <set> <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" name="person"/> <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" name="addresses"/> </set> </property> </bean> </beans>
      
      







人のクラス
 public class Person { private String name; private Integer age; public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public Integer getAge() { return age; } @Override public String toString() { return name + ":" + age; }
      
      







プロジェクト構造



画像



ここでpom.xml
 <?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.example</groupId> <artifactId>demoCacheAble</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>DemoCacheAble</name> <description>Demo project for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.6.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-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>
      
      







Oracle PL-SQL関数のキャッシュ



最後に、DBMSの能力を無視せずに使用する人は、追加または代替として、DBレベルでキャッシュを使用できます。 そのため、たとえばOracleでは、通常の関数を追加して結果をキャッシュする関数にエレガントに変えることはできません
RESULT_CACHE


例:



 CREATE OR REPLACE FUNCTION GET_COUNTRY_NAME(P_CODE IN VARCHAR2) RETURN VARCHAR2 RESULT_CACHE IS CODE_RESULT VARCHAR2(50); BEGIN SELECT COUNTRY_NAME INTO CODE_RESULT FROM COUNTRIES WHERE COUNTRY_ID = P_CODE; --    dbms_lock.sleep (1); RETURN(CODE_RESULT); END;
      
      





テーブル内のデータを変更すると、キャッシュが再構築されます。次を使用してキャッシュルールを微調整できます。
RELIES_ON(...)
素材

キャッシュの抽象化



All Articles