JAvaライブラリ関連クエリーツールクラス

32643 ワード

質問:
企業の業務が拡大したため、各サブシステムは次々と異なるデータソースに移行し、導入され、拡張が容易になったが、いくつかの問題が発生した.
例として、「受注」(受注サブシステムにある)リストを照会する際に、関連する「ユーザー」(アカウントサブシステムにある)の名前を照会する必要があるが、この場合、データが異なるデータソースに格納されているため、1つの連結テーブルのsqlですべてのデータを取得することはできないが、2回のデータベース照会を行い、異なるデータソースからそれぞれデータを取得しなければならない.Webサーバで関連マッピングを行います.しばらく観察したところ,関連マッピングを行うコードの大部分がテンプレート化されていることが分かったため,これらのテンプレートコードを抽象化し,開発を簡素化し,コードの可読性を向上させる考えが生まれた.同時に、同じデータ・ソースでも、複数のテーブル・クエリーのニーズを単一のテーブル・複数回のクエリーに変換できれば、コードの結合を低減し、データベースの効率を向上させることができます.
設計の主な考え方:
リレーショナル・データベース:
一対一の関係は、一般に、一方のデータテーブル構造に1つのビジネス上の外部キーが別のテーブルに関連付けられているプライマリ・キー(受注とユーザーが一対一の関係である場合、受注テーブルに外部キーがユーザー・テーブルに対応するプライマリ・キー)として表されます.
一対多の関係は、一般に、複数のデータに1つの業務上の外部キーが関連する一方のプライマリ・キー(店舗と受注が一対多の関係である場合、受注テーブルに外部キーが存在する場合、店舗のプライマリ・キーに対応する)として表される.
非リレーショナル・データベースでは、次のようになります.
一対一の関係は、一般に、一方に属性が存在し、値が関連する他方のデータ・オブジェクト(受注とユーザーが一対一の関係である場合、受注オブジェクトにユーザー属性が存在する)として表されます.
一対多の関係は一般に、一方に1つの属性が存在し、値が関連する他方のデータオブジェクトリスト(店舗と所属受注が一対多の関係である場合、店舗オブジェクトには1つの受注リスト(List)属性が存在する)と表される.
Javaのオブジェクトメカニズムは,自然に非関係型のデータモデルをサポートするため,クエリされた2つのリストを要求に合ったマッピングすればよいという大まかな考え方が見られる.
pojoクラス:
public class OrderForm {
    /**
     *   id
     * */
    private String id;
    /**
     *     id
     * */
    private String shopID;
    /**
     *      id
     * */
    private String customerID;
    /**
     *      model
     * */
    private Customer customer;
}

public class Customer {
    /**
     *   id
     * */
    private String id;
    /**
     *   
     * */
    private String userName;
}

public class Shop {
    /**
     *   id
     * */
    private String id;
    /**
     *    
     * */
    private String shopName;
    /**
     *      (      N       )
     * */
    private List orderFormList;
}

補助ツール関数:
  /***
     *    keyName     bean   get        
     * @param keyName    
     * @return    get        
     */
    private static String makeGetMethodName(String keyName){
        //:::          
        String newKeyName = transFirstCharUpperCase(keyName);

        return "get" + newKeyName;
    }

    /***
     *    keyName     bean   set        
     * @param keyName    
     * @return    set        
     */
    private static String makeSetMethodName(String keyName){
        //:::          
        String newKeyName = transFirstCharUpperCase(keyName);

        return "set" + newKeyName;
    }

    /**
     *               
     * @param str          
     * @return           
     */
    private static String transFirstCharUpperCase(String str){
        return str.replaceFirst(str.substring(0, 1), str.substring(0, 1).toUpperCase());
    }

    /**
     *               
     *
     *           ,      
     * @return         false,     true
     * */
    private static boolean needTrans(List beanList,List dataList){
        if(listIsEmpty(beanList) || listIsEmpty(dataList)){
            return false;
        }else{
            return true;
        }
    }

    /**
     *       
     * */
    private static boolean listIsEmpty(List list){
        if(list == null || list.isEmpty()){
            return true;
        }else{
            return false;
        }
    }

/**
     *  javaBean   list     map, key bean        
     *
     * @param beanList list   
     * @param keyName    map  key
     * @return
     * @throws Exception
     */
    public static Map beanListToMap(List beanList,String keyName) throws Exception{
        //:::    map
        Map map = new HashMap<>();

        //::: keyName     get     
        String getMethodName = makeGetMethodName(keyName);

        //:::  beanList
        for(Object obj : beanList){
            //:::       hashMap  
            if(obj.getClass() == HashMap.class){
                Map currentMap = (Map)obj;

                //:::  keyName map      key
                String result = (String)currentMap.get(keyName);

                //:::  map (  key  ,       )
                map.put(result,currentMap);
            }else{
                //:::     pojo  
                //:::  get  
                Method getMethod = obj.getClass().getMethod(getMethodName);

                //:::  get   bean       key
                String result = (String)getMethod.invoke(obj);

                //:::  map (  key  ,       )
                map.put(result,obj);
            }
        }
        //:::    
        return map;
    }

1対1の接続インタフェース定義:
/**
      *       :  beanKeyName  dataKeyName       
      *
      * @param beanList         beanList(  )
      * @param beanKeyName   beanList     key   
      * @param beanModelName  beanList           value   
      * @param dataList        data  
      * @param dataKeyName       data     key   
      *
      * @throws Exception
      */
     public static void oneToOneLinked(List beanList, String beanKeyName, String beanModelName, List dataList, String dataKeyName) throws Exception { }

上記の1対1の接続例を持ち込むと、beanListは受注リスト(List)であり、beanKeyNameは受注がユーザを関連付けるためのフィールド名(例えば、外部キー「OrderForm.customerID」)であり、beanModelNameはユーザクラスを格納するためのフィールド名(「例えばOrderForm.customer」)であり、dataListは顧客リスト(List)であり、DataKeyNameは、関連付けられたデータのkey(プライマリ・キー「Customer.id」)です.
1対1の接続コードの実装:
/**
     *       :  beanKeyName  dataKeyName       
     *
     * @param beanList         beanList(  )
     * @param beanKeyName   beanList     key   
     * @param beanModelName  beanList           value   
     * @param dataList        data  
     * @param dataKeyName       data     key   
     *
     * @throws Exception
     */
    public static void oneToOneLinked(List beanList, String beanKeyName, String beanModelName, List dataList, String dataKeyName) throws Exception {
        //:::       ,    
        if(!needTrans(beanList,dataList)){
            return;
        }
        //:::         ,         key,   map,       
        Map dataMap = beanListToMap(dataList,dataKeyName);

        //:::        
       matchedDataToBeanList(beanList,beanKeyName,beanModelName,dataMap);
  }

/**
     *             ,      beanList  
     * @param beanList         beanList(  )
     * @param beanKeyName   beanList          
     * @param beanModelName  beanList              
     * @param dataMap  data          key   map
     * @throws Exception
     */
    private static void matchedDataToBeanList(List beanList, String beanKeyName, String beanModelName, Map dataMap) throws Exception {
        //:::  beanList      key get   
        String beanGetMethodName = makeGetMethodName(beanKeyName);
        //:::  beanList      model set   
        String beanSetMethodName = makeSetMethodName(beanModelName);

        //:::    beanList
        for(Object bean : beanList){
            //:::  bean key method  
            Method beanGetMethod = bean.getClass().getMethod(beanGetMethodName);

            //:::       key
            String currentBeanKey = (String)beanGetMethod.invoke(bean);

            //:::        map        
            Object matchedData = dataMap.get(currentBeanKey);

            //:::          
            if(matchedData != null){
                //:::  bean   model set  
                Class clazz = matchedData.getClass();

                //:::         hashMap
                if(clazz == HashMap.class){
                    //:::    map class    set  
                    clazz = Map.class;
                }

                //:::    bean          set  
                Method beanSetMethod = bean.getClass().getMethod(beanSetMethodName,clazz);
                //:::  set  ,                model   
                beanSetMethod.invoke(bean,matchedData);
            }
        }
    }

1対の複数接続インタフェースの定義:
/**
     *       :  oneKeyName  manyKeyName       
     *
     * @param oneDataList       '  '     
     * @param oneKeyName        '  '     key   
     * @param oneModelName      '  '      '  '        
     * @param manyDataList      '  '     
     * @param manyKeyName       '  '     key   
     *
     *    :  '  '    '  '     oneModelName     List
     *
     * @throws Exception
     */
    public static void oneToManyLinked(List oneDataList,String oneKeyName,String oneModelName,List manyDataList,String manyKeyName) throws Exception {}

上記の一対のマルチコネクションの例を持ち込むと、oneDataListは店舗リスト(List)であり、oneKeyNameは店舗が受注を関連付けるためのフィールド名(例えばメインキー「Shop.id」)であり、oneModelNameは受注リストを格納するためのフィールド名(例えば「Shop.orderFomrList」)であり、manyDataListはマルチリスト(List)であり、manyKeyNameは、関連付けられたデータのkey(例えば、外部キー「OrderFrom.shopID」)である.
1対のマルチ接続コード実装:
 /**
     *       :  oneKeyName  manyKeyName       
     *
     * @param oneDataList       '  '     
     * @param oneKeyName        '  '     key   
     * @param oneModelName      '  '      '  '        
     * @param manyDataList      '  '     
     * @param manyKeyName       '  '     key   
     *
     *    :  '  '    '  '     oneModelName     List
     *
     * @throws Exception
     */
    public static void oneToManyLinked(List oneDataList,String oneKeyName,String oneModelName,List manyDataList,String manyKeyName) throws Exception {
        if(!needTrans(oneDataList,manyDataList)){
            return;
        }
        //::: '  '  ,      key,  map,    
        Map oneDataMap = beanListToMap(oneDataList,oneKeyName);

        //:::  '  '   '  '     get   
        String oneDataModelGetMethodName = makeGetMethodName(oneModelName);
        //:::  '  '   '  '     set   
        String oneDataModelSetMethodName = makeSetMethodName(oneModelName);

        //:::  '  '     get   
        String manyDataKeyGetMethodName = makeGetMethodName(manyKeyName);

        try {
            //:::  '  '  
            for (Object manyDataItem : manyDataList) {
                //:::'  '    key  
                String manyDataItemKey;
                //:::    '  '         hashMap
                if(manyDataItem.getClass() == HashMap.class){
                    //:::   hashMap   ,   Map  
                    Map manyDataItemMap = (Map)manyDataItem;

                    //:::    key       key      
                    manyDataItemKey = (String)manyDataItemMap.get(manyKeyName);
                }else{
                    //:::      pojo  ,       get     key      

                    //:::  '  '   key method  
                    Method manyDataKeyGetMethod = manyDataItem.getClass().getMethod(manyDataKeyGetMethodName);
                    //:::  '  '   get      '  '      key  
                    manyDataItemKey = (String) manyDataKeyGetMethod.invoke(manyDataItem);
                }
                //:::  '  '     key  '  ' map        key    '  '    
                Object matchedOneData = oneDataMap.get(manyDataItemKey);

                //:::        ,     
                if(matchedOneData != null){
                    //:::       '  '      '  '        
                    setManyDataToOne(matchedOneData,manyDataItem,oneDataModelGetMethodName,oneDataModelSetMethodName);
                }
            }
        }catch(Exception e){
            throw new Exception(e);
        }
    }

 /**
     *   '  '      '  '    
     * @param oneData     '  '  
     * @param manyDataItem        '    '
     * @param oneDataModelGetMethodName      get   
     * @param oneDataModelSetMethodName      set   
     * @throws Exception
     */
    private static void setManyDataToOne(Object oneData,Object manyDataItem,String oneDataModelGetMethodName,String oneDataModelSetMethodName) throws Exception {
        //:::   '  '      '  '     get  
        Method oneDataModelGetMethod = oneData.getClass().getMethod(oneDataModelGetMethodName);
        //::: '  '      '  '     set  
        Method oneDataModelSetMethod;
        try {
            //::: '  ' set    
            oneDataModelSetMethod = oneData.getClass().getMethod(oneDataModelSetMethodName,List.class);
        }catch(NoSuchMethodException e){
            throw new Exception("        '  'set  ");
        }

        //:::    '  '  get       
        Class modelType = oneDataModelGetMethod.getReturnType();
        //::: get        List
        if(modelType.equals(List.class)){
            //:::  get  ,      
            List modelList = (List)oneDataModelGetMethod.invoke(oneData);

            //:::         null
            if(modelList == null){
                //:::      List
                List newList = new ArrayList<>();
                //:::    '  '    list
                newList.add(manyDataItem);
                //:::        List    '  '   
                oneDataModelSetMethod.invoke(oneData,newList);
            }else{
                //:::       List

                //:::   '  '    list
                modelList.add(manyDataItem);
            }
        }else{
            throw new Exception("      ,     model     list  ");
        }
    }

テスト例はgithubの上にありますhttps://github.com/1399852153/linkedQueryUtil.
これは私の最初の技術ブログで、レイアウトにしても共有にしてもまだ多くの不足点があります.皆さんが指摘して、お互いに交流して、お互いに進歩してほしいと思っています.