تخزين البيانات - Java Spring

قراءة نفس البيانات بشكل متكرر ، والسؤال الذي يطرح نفسه التحسين ، والبيانات لا تتغير أو نادرا ما تتغير ، وهذه هي كتب مرجعية مختلفة ومعلومات أخرى ، أي وظيفة الحصول على البيانات عن طريق المفتاح حتمية. هنا ، ربما يفهم الجميع - نحن بحاجة إلى ذاكرة تخزين مؤقت! لماذا تحتاج إلى إجراء بحث عن البيانات أو حسابها في كل مرة؟

لذا سأعرض هنا كيفية إنشاء ذاكرة تخزين مؤقت في Java Spring ، ولأنها ترتبط ارتباطًا وثيقًا بقاعدة البيانات ، ثم كيفية القيام بذلك في نظام إدارة قواعد البيانات باستخدام مثال واحد محدد.

المحتويات

  • مخبأ في الربيع
  • ذاكرة التخزين المؤقت في وظائف Oracle PL-SQL

مخبأ في الربيع


ثم يأتي كل شيء بنفس الطريقة تقريبًا ، في جافا يستخدمون العديد من HasMap و ConcurrentMap وما إلى ذلك. في الربيع أيضًا ، هناك حل لهذا ، بسيط ومريح وفعال. أعتقد أن هذا سيساعد في معظم الحالات في حل المشكلة. وهكذا ، كل ما هو مطلوب هو تمكين ذاكرة التخزين المؤقت وتعليق الوظيفة.

إتاحة الوصول إلى ذاكرة التخزين المؤقت

@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(""); } } 

في الاختبار أتصل مرتين

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

، المرة الأولى التي يتم فيها إجراء مكالمة ، بحث ، المرة الثانية التي يتم فيها أخذ النتيجة من ذاكرة التخزين المؤقت. هذا مرئي في وحدة التحكم.

الصورة

بشكل ملائم ، يمكنك تحسين الوظائف الحالية بشكل نقطي. إذا كانت الوظيفة تحتوي على أكثر من وسيطة واحدة ، فيمكنك تحديد اسم المعلمة لاستخدامها كمفتاح.

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

هناك مخططات أكثر تعقيدًا للحصول على مفتاح ، وهذا في الوثائق.

ولكن بالطبع سيكون السؤال هو كيفية تحديث البيانات في ذاكرة التخزين المؤقت؟ هناك نوعان من التعليقات التوضيحية لهذا الغرض.

الأول هو @CachePut

ستعمل الوظيفة مع هذا التعليق التوضيحي دائمًا على استدعاء الرمز ، ووضع النتيجة في ذاكرة التخزين المؤقت ، بحيث يمكنها تحديث ذاكرة التخزين المؤقت.

سأضيف طريقتين إلى المستودع: حذف وإضافة شخص

  public boolean delete(String name) { final Person person = findByName(name); return persons.remove(person); } public boolean add(Person person) { return persons.add(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 ، يشار إلى هذا على النحو التالي:

تكوين الربيع. 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 ، لكنهم يستخدمونها ، يمكنهم استخدام التخزين المؤقت على مستوى قاعدة البيانات ، بالإضافة إلى ذلك أو كبديل. على سبيل المثال ، في 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 (...)
المواد
تجريد ذاكرة التخزين المؤقت

Source: https://habr.com/ru/post/ar427187/


All Articles