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

وهكذا في Spring يوجد KeyValueOperations ، وهو مشابه لمستودع Spring Data ، لكنه يعمل على مفهوم Key-Value ويضع البيانات في بنية HashMap (
كتبت عن مستودعات Spring Data هنا ). يمكن أن تكون الكائنات من أي نوع ، الشيء الرئيسي هو أن المفتاح محدد.
public class Status { @org.springframework.data.annotation.Id private long statusId; private String code; private String name; ....
هنا المفتاح هو statusId ، ويشار إلى المسار الكامل للتعليقات التوضيحية على وجه التحديد ، في المستقبل سأستخدم JPA Entity ، وهناك أيضًا معرف هناك ، لكن يرتبط بالفعل بقاعدة البيانات.
لدى KeyValueOperations طرق مماثلة كما في مستودعات بيانات الربيع
interface KeyValueOperations { <T> T insert(T objectToInsert); void update(Object objectToUpdate); void delete(Class<?> type); <T> T findById(Object id, Class<T> type); <T> Iterable<T> find(KeyValueQuery<?> query, Class<T> type); .... .
حتى تتمكن من تحديد java KeyValueOperations التكوين لفصل الربيع
@SpringBootApplication public class DemoSpringDataApplication { @Bean public KeyValueOperations keyValueTemplate() { return new KeyValueTemplate(keyValueAdapter()); } @Bean public KeyValueAdapter keyValueAdapter() { return new MapKeyValueAdapter(ConcurrentHashMap.class); }
يتم سرد فئة تخزين القاموس هنا - ConcurrentHashMap
وبما أنني سأعمل مع قواميس JPA Entity ، فسوف أقوم بتوصيل اثنين منهم بهذا المشروع.
هذا هو قاموس "الحالة" و "البطاقة"
@Entity public class Status { @org.springframework.data.annotation.Id private long statusId; private String code; private String name; @Id @Column(name = "STATUS_ID") public long getStatusId() { return statusId; } .... @Entity public class Card { @org.springframework.data.annotation.Id private long cardId; private String code; private String name; @Id @Column(name = "CARD_ID") public long getCardId() { return cardId; } ...
هذه كيانات قياسية تتوافق مع الجداول الموجودة في قاعدة البيانات ، وألفت الانتباه إلى توضيحيي معرف لكل كيان ، أحدهما لـ JPA والآخر لـ KeyValueOperations
بنية القواميس متشابهة ، مثال واحد منها
create table STATUS ( status_id NUMBER not null, code VARCHAR2(20) not null, name VARCHAR2(50) not null );
مستودعات بيانات الربيع الخاصة بهم:
@Repository public interface CardCrudRepository extends CrudRepository<Card, Long> { } @Repository public interface StatusCrudRepository extends CrudRepository<Status, Long> { }
وإليك مثال DictionaryProvider نفسه حيث نقوم بتوصيل مستودعات Spring Data و KeyValueOperations
@Service public class DictionaryProvider { private static Logger logger = LoggerFactory.getLogger(DictionaryProvider.class); private Map<Class, CrudRepository> repositoryMap = new HashMap<>(); @Autowired private KeyValueOperations keyValueTemplate; @Autowired private StatusCrudRepository statusRepository; @Autowired private CardCrudRepository cardRepository; @PostConstruct public void post() { repositoryMap.put(Status.class, statusRepository); repositoryMap.put(Card.class, cardRepository); } public <T> Optional<T> dictionaryById(Class<T> clazz, long id) { Optional<T> optDictionary = keyValueTemplate.findById(id, clazz); if (optDictionary.isPresent()) { logger.info("Dictionary {} found in keyValueTemplate", optDictionary.get()); return optDictionary; } CrudRepository crudRepository = repositoryMap.get(clazz); optDictionary = crudRepository.findById(id); keyValueTemplate.insert(optDictionary.get()); logger.info("Dictionary {} insert in keyValueTemplate", optDictionary.get()); return optDictionary; } ....
يتم تثبيت الحقن التلقائي فيه لمستودعات التخزين و KeyValueOperations ، ومن ثم المنطق البسيط (هنا ، دون التحقق من وجود قيمة خالية ، إلخ) ، سنبحث في قاموس keyValueTemplate ، إذا كان هناك ، فإننا نرجع ، وإلا فإننا نستخرج من قاعدة البيانات عبر crudRepository ونضع في keyValueTemplate ، ونقدم خارج.
ولكن إذا كان كل هذا سيقتصر فقط على البحث الرئيسي ، فمن المحتمل ألا يكون هناك شيء خاص. وهكذا KeyValueOperations لديها مجموعة واسعة من عمليات CRUD ، والطلبات. فيما يلي مثال لعملية بحث في نفس keyValueTemplate ، ولكن بالفعل بواسطة الرمز باستخدام استعلام KeyValueQuery.
public <T> Optional<T> dictionaryByCode(Class<T> clazz, String code) { KeyValueQuery<String> query = new KeyValueQuery<>(String.format("code == '%s'", code)); Iterable<T> iterable = keyValueTemplate.find(query, clazz); Iterator<T> iterator = iterable.iterator(); if (iterator.hasNext()) { return Optional.of(iterator.next()); } return Optional.empty(); }
وهذا أمر مفهوم ، إذا قمت في وقت سابق بالبحث بمعرف وتم إدخال الكائن في keyValueTemplate ، فإن البحث عن طريق رمز نفس الكائن سيعيده بالفعل من keyValueTemplate ، ولن يكون هناك وصول إلى قاعدة البيانات. يستخدم الربيع التعبير اللغة لوصف الطلب.
أمثلة الاختبار:
البحث عن معرف
private void find() { Optional<Status> status = dictionaryProvider.dictionaryById(Status.class, 1L); Assert.assertTrue(status.isPresent()); Optional<Card> card = dictionaryProvider.dictionaryById(Card.class, 100L); Assert.assertTrue(card.isPresent()); }
البحث عن طريق الرمز
private void findByCode() { Optional<Card> card = dictionaryProvider.dictionaryByCode(Card.class, "VISA"); Assert.assertTrue(card.isPresent()); }
يمكنك الحصول على قوائم البيانات من خلال
<T> Iterable<T> find(KeyValueQuery<?> query, Class<T> type);
يمكنك تحديد الفرز في الطلب
query.setSort(Sort.by(DESC, "name"));
المواد:
قيمة بيانات الربيعمشروع جيثب