GenericDelegator.java    protected GenericDelegator(String delegatorName) throws GenericEntityException {         if (Debug.infoOn()) Debug.logInfo("Creating new Delegator with name \"" + delegatorName + "\".", module); 
        this.delegatorName = delegatorName;         if (keepLocalReaders) {    /*       读取 components\accounting\entitydef\entitymodel.xml等文件,       这些文件是配置在components\...\ofbiz-component.xml中    */             modelReader = ModelReader.getModelReader(delegatorName); 
            /*      Group的方法和Model的读取方法类似,也是先从entitymodel.xml和ofbiz-component.xml      取到资源文件,然后加载.      有一点须要说明:         */              modelGroupReader = ModelGroupReader.getModelGroupReader(delegatorName);         } 
        primaryKeyCache = new UtilCache("entity.FindByPrimaryKey." + delegatorName, 0, 0, true);         allCache = new UtilCache("entity.FindAll." + delegatorName, 0, 0, true);         andCache = new UtilCache("entity.FindByAnd." + delegatorName, 0, 0, true); 
        // initialize helpers by group   /*    一个Group包含多个entitymodel.不同的Group可以对应不同的数据源,也就是说,可以和多个数据库相连   */         Iterator groups = UtilMisc.toIterator(getModelGroupReader().getGroupNames()); 
        while (groups != null && groups.hasNext()) {    /*       取到entityengine.xml中定义的group       比如:              <delegator name="default" entity-model-reader="main" entity-group-reader="main" entity-eca-reader="main" distributed-cache-clear-enabled="false">                <group-map group-name="org.ofbiz" datasource-name="localmssql"/>          <group-map group-name="other" datasource-name="localpostgres"/>             </delegator>       你定义entitygroup.xml文件中就可以这样定义             <entitygroup>               <entity-group group="other" entity="SequenceValueItem" />               <entity-group group="org.ofbiz" entity="SequenceValueItem" />             </entitygroup> 
             */             String groupName = (String) groups.next();             String helperName = this.getGroupHelperName(groupName); 
            if (Debug.infoOn()) Debug.logInfo("Delegator \"" + delegatorName + "\" initializing helper \"" +                     helperName + "\" for entity group \"" + groupName + "\".", module);             TreeSet helpersDone = new TreeSet(); 
            if (helperName != null && helperName.length() > 0) {                 // make sure each helper is only loaded once                 if (helpersDone.contains(helperName)) {                     if (Debug.infoOn()) Debug.logInfo("Helper \"" + helperName + "\" already initialized, not re-initializing.", module);                     continue;                 }                 helpersDone.add(helperName);                 // pre-load field type defs, the return value is ignored     /*       读取group 对应的fieldtype,这些文件处在entity/fieldtype          */                 ModelFieldTypeReader.getModelFieldTypeReader(helperName);                 // get the helper and if configured, do the datasource check                 GenericHelper helper = GenericHelperFactory.getHelper(helperName);                 /*        生成group对应的datasourceinfo     */                 EntityConfigUtil.DatasourceInfo datasourceInfo = EntityConfigUtil.getDatasourceInfo(helperName); 
                if (datasourceInfo.checkOnStart) {                     if (Debug.infoOn()) Debug.logInfo("Doing database check as requested in entityengine.xml with addMissing=" + datasourceInfo.addMissingOnStart, module);                     try {       /*         1:读取group对应数据库所在的表         2:读取group对应数据所有的列         3:读到group对应的索引等...         它的读取方法有点特别,至少我是第一次见过,一般我们是从系统表里面去取,而它不是.         有兴趣可以看看DatabaseUtil.java里面的 checkdb方法,简单地copy一些代码出来         取table          DatabaseMetaData dbData = this.getDatabaseMetaData(connection, messages);          String[] types = {"TABLE", "VIEW", "ALIAS", "SYNONYM"};          tableSet = dbData.getTables(null, lookupSchemaName, null, types);                           取 col                            ResultSet rsCols = dbData.getColumns(null, lookupSchemaName, null, null);         4:this.getModelEntityMapByGroup(groupName)表示得到group对应的所有entity         checkDataSource的作用很明显,它用读到tables,columns,indexes等与entitymodel相比较,         如果不同,它就以entitymodel为基准,修改数据库,修改时都采用alert table等sql语句,         这样,ofbiz服务启动时,就会自动的把entitymodel中对应的关系反映到数据库,由于entitymodel]         并不是象hibenate那样,对应一个JavaBean,所以我们可以在系统运行时,很方便的修改entitymodel,         进而修改数据库,而不用动另何java文件. 
      */                         helper.checkDataSource(this.getModelEntityMapByGroup(groupName), null, datasourceInfo.addMissingOnStart);                     } catch (GenericEntityException e) {                         Debug.logWarning(e.getMessage(), module);                     }                 }             }         } 
        //time to do some tricks with manual class loading that resolves circular dependencies, like calling services...         ClassLoader loader = Thread.currentThread().getContextClassLoader(); 
        // if useDistributedCacheClear is false do nothing since the         // distributedCacheClear member field with a null value will cause the         // dcc code to do nothing         if (getDelegatorInfo().useDistributedCacheClear) {             // initialize the distributedCacheClear mechanism             String distributedCacheClearClassName = getDelegatorInfo().distributedCacheClearClassName; 
            try {                 Class dccClass = loader.loadClass(distributedCacheClearClassName);                 this.distributedCacheClear = (DistributedCacheClear) dccClass.newInstance();                 this.distributedCacheClear.setDelegator(this, getDelegatorInfo().distributedCacheClearUserLoginId);             } catch (ClassNotFoundException e) {                 Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " was not found, distributed cache clearing will be disabled", module);             } catch (InstantiationException e) {                 Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " could not be instantiated, distributed cache clearing will be disabled", module);             } catch (IllegalAccessException e) {                 Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " could not be accessed (illegal), distributed cache clearing will be disabled", module);             } catch (ClassCastException e) {                 Debug.logWarning(e, "DistributedCacheClear class with name " + distributedCacheClearClassName + " does not implement the DistributedCacheClear interface, distributed cache clearing will be disabled", module);             }         } 
              try {    /*       安装enitty eca处理器    */             Class eecahClass = loader.loadClass(ECA_HANDLER_CLASS_NAME);             this.entityEcaHandler = (EntityEcaHandler) eecahClass.newInstance();             this.entityEcaHandler.setDelegator(this);         } catch (ClassNotFoundException e) {             Debug.logWarning(e, "EntityEcaHandler class with name " + ECA_HANDLER_CLASS_NAME + " was not found, Entity ECA Rules will be disabled", module);         } catch (InstantiationException e) {             Debug.logWarning(e, "EntityEcaHandler class with name " + ECA_HANDLER_CLASS_NAME + " could not be instantiated, Entity ECA Rules will be disabled", module);         } catch (IllegalAccessException e) {             Debug.logWarning(e, "EntityEcaHandler class with name " + ECA_HANDLER_CLASS_NAME + " could not be accessed (illegal), Entity ECA Rules will be disabled", module);         } catch (ClassCastException e) {             Debug.logWarning(e, "EntityEcaHandler class with name " + ECA_HANDLER_CLASS_NAME + " does not implement the EntityEcaHandler interface, Entity ECA Rules will be disabled", module);         }     } 
    /** Gets the name of the server configuration that corresponds to this delegator      * @return server configuration name      */     public String getDelegatorName() {         return this.delegatorName;     } 
  ModelReader.java 
 public static ModelReader getModelReader(String delegatorName) throws GenericEntityException {         /*     EntityConfigUtil将读取component\entity\config\entityengine.xml文件   */   EntityConfigUtil.DelegatorInfo delegatorInfo = EntityConfigUtil.getDelegatorInfo(delegatorName); 
        if (delegatorInfo == null) {             throw new GenericEntityConfException("Could not find a delegator with the name " + delegatorName);         } 
        String tempModelName = delegatorInfo.entityModelReader;         ModelReader reader = (ModelReader) readers.get(tempModelName); 
        if (reader == null) { // don't want to block here             synchronized (ModelReader.class) {                 // must check if null again as one of the blocked threads can still enter                 reader = (ModelReader) readers.get(tempModelName);                 if (reader == null) {      /*         1:读取entityengine.xml定义的model文件         2:读取ofbiz-component.xml取到的model文件      */                     reader = new ModelReader(tempModelName);                     // preload caches...      /*        1:加载所有的entity        每个entity对应一个ModelEntity对象         2:系统默认,每个entity将自动加上:lastUpdatedStamp,lastUpdatedTxStamp          ,createdStamp,createdStamp,       这些是不需要在entitymodel.xml中定义的                       3:ofbiz3中entitymodel.xml中每个node将会对应一个对象.          比如:       <field name="budgetId" type="id-ne"></field>       对应ModelField对象           <relation type="many" rel-entity-name="BudgetRevision">            对应 ModelRelation 对象             <index name="GLACCT_UNQCD" unique="true">                      <index-field name="accountCode"/>              </index>            对应 ModelIndex 对象       等等      */                     reader.getEntityCache();                     readers.put(tempModelName, reader);                 }             }         }         return reader;     }
   
 
  |