Spring Data Key-Valueリポジトリを使用したデータ検索の整理

対話型システムは、さまざまなディレクトリ(データディクショナリ)を使用します。これらは、さまざまなステータス、コード、名前などです。原則として、それらは多くあり、それぞれは大きくありません。 構造内では、コード、ID、名前などの共通の属性を持っていることがよくあります。アプリケーションコードには、コードごと、参照IDごとのさまざまな検索、比較があります。 検索は拡張できます。たとえば、IDによる検索、コードによる検索、条件によるリストの取得、並べ替えなどです。その結果、ディレクトリがキャッシュされ、データベースへの頻繁なアクセスが減少します。 ここでは、これらの目的にSpring Data Key-Valueリポジトリがどのように役立つか例を示します。 主なアイデアは次のとおりです。Key-Valueリポジトリでの高度な検索と、オブジェクトがない場合は、データベース内のSpring Dataリポジトリを検索してから、Key-Valueリポジトリに配置します。



画像



したがって、Springには、Spring Dataリポジトリに似たKeyValueOperationsがありますが、Key-Valueの概念に基づいて動作し、HashMap構造にデータを配置します( Spring Dataリポジトリについては ここで説明しました )。 オブジェクトはどのタイプでもかまいませんが、主なことはキーが指定されていることです。



public class Status { @org.springframework.data.annotation.Id private long statusId; private String code; private String name; ....
      
      





ここで、キーはstatusIdであり、注釈の完全なパスが具体的に示されています。将来的にはJPAエンティティを使用し、そこにもIdがありますが、すでにデータベースに関連しています。

KeyValueOperationsには、Spring Dataリポジトリと同様のメソッドがあります



 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); .... .
      
      





したがって、Spring Beanの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辞書を使用するため、そのうち2つをこのプロジェクトに接続します。



これは「ステータス」と「カード」の辞書です



 @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; } ...
      
      





これらはデータベース内のテーブルに対応する標準エンティティです。各エンティティの2つのIdアノテーションに注目します。1つはJPA用、もう1つはKeyValueOperations用です



辞書の構造は似ており、そのうちの1つの例



 create table STATUS ( status_id NUMBER not null, code VARCHAR2(20) not null, name VARCHAR2(50) not null ); -- Create/Recreate primary, unique and foreign key constraints alter table STATUS add constraint STATUS_PK primary key (STATUS_ID)
      
      





それらのSpring Dataリポジトリ:



 @Repository public interface CardCrudRepository extends CrudRepository<Card, Long> { } @Repository public interface StatusCrudRepository extends CrudRepository<Status, Long> { }
      
      





次に、Spring DataリポジトリとKeyValueOperationsを接続するDictionaryProviderサンプル自体を示します



 @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の自動インジェクトがインストールされ、次に単純なロジック(ここでは、nullなどをチェックせずに)、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(); }
      
      





そして、以前にIDで検索し、オブジェクトがkeyValueTemplateに入った場合、同じオブジェクトのコードで検索するとkeyValueTemplateから返され、データベースにアクセスできなくなることは理解できます。 Spring Expression Languageは、リクエストを記述するために使用されます。



テスト例:

ID検索



  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"));
      
      





材料:



スプリングデータのキー値



Githubプロジェクト



All Articles