Redisバッチ・クエリー・テンプレート

3383 ワード

シーン
商品情報の照会など、開発時に一括キャッシュの問題に遭遇することが多い
  • は、商品Idリストを入力し、Redisデータの存在を問い合わせると、戻りリスト
  • に入れる.
  • が存在しないデータはデータベースを検索し、Redis
  • に入れる.
  • 上の2ステップのデータ統合は、
  • の偽コードを返す.
    list.ForEach(str->{
    	dto = redis.get(str);
    		if(dto != null){
    		resultList.add(dto);
    	}else{
    		mustQuerySQL.add(str);
    	}
    })
    if(CollectionUtils.isNotEmpty(mustQuerySQL)){
    	querysqlList = querySQL(mustQuerySQL);
    	querySqlList.ForEach(dto->{
    		redis.put(dto);	
    		resultList.add(dto);
    	}
    })
    return resultList;
    

    問題はプロジェクトでこのようなパターンをよく使うことですが、手順を簡略化する方法はありますか?
    テンプレートメソッドモード
    テンプレートメソッドモデルは、動作設計モデルです.テンプレート・メソッドは、親カテゴリに定義された複数の他のメソッドを呼び出す親メソッドを定義するメソッドです.これらのメソッドは抽象メソッドだけが実作していない可能性があります.テンプレート・メソッドは、これらの抽象メソッドの実行順序のみを決定します.これらの抽象メソッドの実作はサブカテゴリが担当し、サブカテゴリはテンプレート・メソッドの上書きを許可しません.テンプレートメソッドモードを使用して、Redisからデータを取得し、SQLからデータを取得し、SQLからデータをRedisに入れてサブクラスに実装することができます.
    インプリメンテーション
    コードは次のとおりです.
    public abstract class RedisUtil  {
    
        public final List getList(List list){
            List resultList = new ArrayList<>();
            List mustQuery = new ArrayList<>();
            list.forEach(str->{
                T o = queryForRedis(str);
                if(o != null){
                    resultList.add(o);
                }else {
                    mustQuery.add(str);
                }
            });
            if(CollectionUtils.isNotEmpty(mustQuery)) {
                List sql = queryForSQL(mustQuery);
                sql.forEach(dto->{
                    setForRedis(dto);
                    resultList.add(dto);
                });
            }
            return resultList;
        }
    
        protected abstract T queryForRedis(String str);
    
        protected abstract List queryForSQL(List list);
    
        protected abstract void setForRedis(T t);
    }
    

    サブクラスは匿名クラスを使用するだけで実現できますが、コードにはこのようなコードがあります.
    RedisUtil redisUtil = new RedisUtil() {
                @Override
                protected String queryForRedis(String str) {
                    return null;
                }
    
                @Override
                protected List queryForSQL(List list) {
                    return null;
                }
    
                @Override
                protected void setForRedis(String s) {
    
                }
            };
    

    大量のコードセグメントを占めており、優雅ではないように見えますが、どのように優雅に実現しますか?
    最適化
    匿名クラスが使用されていますが、コードセグメントを占有することで、もちろんエンティティクラスを新規作成して実装できますが、総じて優雅ではありません.JDK 8で提供されている関数インタフェースを使用して実装できます.
    public class RedisUtil  {
        public static  List getList(List list, Function queryRedis, Function,List> querySQL, Consumer setRedis){
            List resultList = new ArrayList<>();
            List mustQuery = new ArrayList<>();
            list.forEach(str->{
                T o = queryRedis.apply(str);
                if(o != null){
                    resultList.add(o);
                }else {
                    mustQuery.add(str);
                }
            });
            if(CollectionUtils.isNotEmpty(mustQuery)) {
                List sql = querySQL.apply(mustQuery);
                sql.forEach(dto->{
                    setRedis.accept(dto);
                    resultList.add(dto);
                });
            }
            return resultList;
        }
    }