Delegator

Delegator是整个ofbiz中数据库访问的入口,具体实现是GenericDelegator类,在这个类中通过

    protected ModelReader modelReader = null;protected ModelGroupReader modelGroupReader = null;

这两个属性变量去查找在xml文件中定义的数据模型

ModelReader

通过ModelReader读取模型实体ModelEntity

 protected Map<String, ModelEntity> entityCache = null;

缓存

   public Map<String, ModelEntity> getEntityCache() throws GenericEntityException {if (entityCache == null) { // don't want to block heresynchronized (ModelReader.class) {// must check if null again as one of the blocked threads can still enterif (entityCache == null) { // now it's safenumEntities = 0;numViewEntities = 0;numFields = 0;numRelations = 0;numAutoRelations = 0;entityCache = new HashMap<String, ModelEntity>();List<ModelViewEntity> tempViewEntityList = new LinkedList<ModelViewEntity>();List<Element> tempExtendEntityElementList = new LinkedList<Element>();UtilTimer utilTimer = new UtilTimer();for (ResourceHandler entityResourceHandler: entityResourceHandlers) {// utilTimer.timerString("Before getDocument in file " + entityFileName);Document document = null;try {document = entityResourceHandler.getDocument();} catch (GenericConfigException e) {throw new GenericEntityConfException("Error getting document from resource handler", e);}if (document == null) {throw new GenericEntityConfException("Could not get document for " + entityResourceHandler.toString());}// utilTimer.timerString("Before getDocumentElement in " + entityResourceHandler.toString());Element docElement = document.getDocumentElement();if (docElement == null) {return null;}docElement.normalize();Node curChild = docElement.getFirstChild();ModelInfo def = ModelInfo.createFromElements(ModelInfo.DEFAULT, docElement);int i = 0;if (curChild != null) {utilTimer.timerString("Before start of entity loop in " + entityResourceHandler.toString());do {boolean isEntity = "entity".equals(curChild.getNodeName());boolean isViewEntity = "view-entity".equals(curChild.getNodeName());boolean isExtendEntity = "extend-entity".equals(curChild.getNodeName());if ((isEntity || isViewEntity) && curChild.getNodeType() == Node.ELEMENT_NODE) {i++;ModelEntity modelEntity = buildEntity(entityResourceHandler, (Element) curChild, i, def);// put the view entity in a list to get ready for the second pass to populate fields...if (isViewEntity) {tempViewEntityList.add((ModelViewEntity) modelEntity);} else {entityCache.put(modelEntity.getEntityName(), modelEntity);}} else if (isExtendEntity && curChild.getNodeType() == Node.ELEMENT_NODE) {tempExtendEntityElementList.add((Element) curChild);}} while ((curChild = curChild.getNextSibling()) != null);} else {Debug.logWarning("No child nodes found.", module);}utilTimer.timerString("Finished " + entityResourceHandler.toString() + " - Total Entities: " + i + " FINISHED");}// all entity elements in, now go through extend-entity elements and add their stufffor (Element extendEntityElement: tempExtendEntityElementList) {String entityName = UtilXml.checkEmpty(extendEntityElement.getAttribute("entity-name"));ModelEntity modelEntity = entityCache.get(entityName);if (modelEntity == null) throw new GenericEntityConfException("Entity to extend does not exist: " + entityName);modelEntity.addExtendEntity(this, extendEntityElement);}// do a pass on all of the view entities now that all of the entities have// loaded and populate the fieldswhile (!tempViewEntityList.isEmpty()) {int startSize = tempViewEntityList.size();Iterator<ModelViewEntity> mveIt = tempViewEntityList.iterator();
TEMP_VIEW_LOOP:while (mveIt.hasNext()) {ModelViewEntity curViewEntity = mveIt.next();for (ModelViewEntity.ModelMemberEntity mve: curViewEntity.getAllModelMemberEntities()) {if (!entityCache.containsKey(mve.getEntityName())) {continue TEMP_VIEW_LOOP;}}mveIt.remove();curViewEntity.populateFields(this);for (ModelViewEntity.ModelMemberEntity mve: curViewEntity.getAllModelMemberEntities()) {ModelEntity me = entityCache.get(mve.getEntityName());me.addViewEntity(curViewEntity);}entityCache.put(curViewEntity.getEntityName(), curViewEntity);}if (tempViewEntityList.size() == startSize) {// Oops, the remaining views reference other entities// that can't be found, or they reference other views// that have some reference problem.break;}}if (!tempViewEntityList.isEmpty()) {StringBuilder sb = new StringBuilder("View entities reference non-existant members:\n");Set<String> allViews = new HashSet<String>();for (ModelViewEntity curViewEntity: tempViewEntityList) {allViews.add(curViewEntity.getEntityName());}for (ModelViewEntity curViewEntity: tempViewEntityList) {Set<String> perViewMissingEntities = new HashSet<String>();Iterator<ModelViewEntity.ModelMemberEntity> mmeIt = curViewEntity.getAllModelMemberEntities().iterator();while (mmeIt.hasNext()) {ModelViewEntity.ModelMemberEntity mme = mmeIt.next();String memberEntityName = mme.getEntityName();if (!entityCache.containsKey(memberEntityName)) {// this member is not a real entity// check to see if it is a viewif (!allViews.contains(memberEntityName)) {// not a view, it's a real missing entityperViewMissingEntities.add(memberEntityName);}}}for (String perViewMissingEntity: perViewMissingEntities) {sb.append("\t[").append(curViewEntity.getEntityName()).append("] missing member entity [").append(perViewMissingEntity).append("]\n");}}throw new GenericEntityConfException(sb.toString());}// auto-create relationshipsTreeSet<String> orderedMessages = new TreeSet<String>();for (String curEntityName: new TreeSet<String>(this.getEntityNames())) {ModelEntity curModelEntity = this.getModelEntity(curEntityName);if (curModelEntity instanceof ModelViewEntity) {// for view-entities auto-create relationships for all member-entity relationships that have all corresponding fields in the view-entity} else {// for entities auto-create many relationships for all type one relationships// just in case we add a new relation to the same entity, keep in a separate list and add them at the endList<ModelRelation> newSameEntityRelations = new LinkedList<ModelRelation>();Iterator<ModelRelation> relationsIter = curModelEntity.getRelationsIterator();while (relationsIter.hasNext()) {ModelRelation modelRelation = relationsIter.next();if (("one".equals(modelRelation.getType()) || "one-nofk".equals(modelRelation.getType())) && !modelRelation.isAutoRelation()) {ModelEntity relatedEnt = null;try {relatedEnt = this.getModelEntity(modelRelation.getRelEntityName());} catch (GenericModelException e) {throw new GenericModelException("Error getting related entity [" + modelRelation.getRelEntityName() + "] definition from entity [" + curEntityName + "]", e);}if (relatedEnt != null) {// create the new relationship even if one exists so we can show what we are looking for in the info message// don't do relationship to the same entity, unless title is "Parent", then do a "Child" automaticallyString title = modelRelation.getTitle();if (curModelEntity.getEntityName().equals(relatedEnt.getEntityName()) && "Parent".equals(title)) {title = "Child";}String description = "";String type = "";String relEntityName = curModelEntity.getEntityName();String fkName = "";ArrayList<ModelKeyMap> keyMaps = new ArrayList<ModelKeyMap>();boolean isAutoRelation = true;Set<String> curEntityKeyFields = new HashSet<String>();for (ModelKeyMap curkm : modelRelation.getKeyMaps()) {keyMaps.add(new ModelKeyMap(curkm.getRelFieldName(), curkm.getFieldName()));curEntityKeyFields.add(curkm.getFieldName());}keyMaps.trimToSize();// decide whether it should be one or many by seeing if the key map represents the complete pk of the relEntityif (curModelEntity.containsAllPkFieldNames(curEntityKeyFields)) {// always use one-nofk, we don't want auto-fks getting in for these automatic onestype = "one-nofk";// to keep it clean, remove any additional keys that aren't part of the PKList<String> curPkFieldNames = curModelEntity.getPkFieldNames();Iterator<ModelKeyMap> nrkmIter = keyMaps.iterator();while (nrkmIter.hasNext()) {ModelKeyMap nrkm =nrkmIter.next();String checkField = nrkm.getRelFieldName();if (!curPkFieldNames.contains(checkField)) {nrkmIter.remove();}}} else {type= "many";}ModelRelation newRel = ModelRelation.create(relatedEnt, description, type, title, relEntityName, fkName, keyMaps, isAutoRelation);ModelRelation existingRelation = relatedEnt.getRelation(title + curModelEntity.getEntityName());if (existingRelation == null) {numAutoRelations++;if (curModelEntity.getEntityName().equals(relatedEnt.getEntityName())) {newSameEntityRelations.add(newRel);} else {relatedEnt.addRelation(newRel);}} else {if (newRel.equals(existingRelation)) {// don't warn if the target title+entity = current title+entityif (Debug.infoOn() && !(title + curModelEntity.getEntityName()).equals(modelRelation.getTitle() + modelRelation.getRelEntityName())) {//String errorMsg = "Relation already exists to entity [] with title [" + targetTitle + "],from entity []";String message = "Entity [" + relatedEnt.getPackageName() + ":" + relatedEnt.getEntityName() + "] already has identical relationship to entity [" +curModelEntity.getEntityName() + "] title [" + title + "]; would auto-create: type [" +newRel.getType() + "] and fields [" + newRel.keyMapString(",", "") + "]";orderedMessages.add(message);}} else {String message = "Existing relationship with the same name, but different specs found from what would be auto-created for Entity [" + relatedEnt.getEntityName() + "] and relationship to entity [" +curModelEntity.getEntityName() + "] title [" + title + "]; would auto-create: type [" +newRel.getType() + "] and fields [" + newRel.keyMapString(",", "") + "]";Debug.logVerbose(message, module);}}} else {String errorMsg = "Could not find related entity ["+ modelRelation.getRelEntityName() + "], no reverse relation added.";Debug.logWarning(errorMsg, module);}}}if (newSameEntityRelations.size() > 0) {for (ModelRelation newRel: newSameEntityRelations) {curModelEntity.addRelation(newRel);}}}}if (Debug.infoOn()) {for (String message : orderedMessages) {Debug.logInfo(message, module);}Debug.logInfo("FINISHED LOADING ENTITIES - ALL FILES; #Entities=" + numEntities + " #ViewEntities=" + numViewEntities + " #Fields=" + numFields + " #Relationships=" + numRelations + " #AutoRelationships=" + numAutoRelations, module);}}}}return entityCache;}

从xml配置文件中读取

ModelEntity

模型实体,所有数据库相关的操作都在这里边进行