From 760efa6c1029254062e6c76e6f7ddc95552c75b4 Mon Sep 17 00:00:00 2001 From: thanos Date: Mon, 2 May 2016 08:37:14 +0800 Subject: [PATCH 1/2] add storeAllBatch etc for delegator --- .../order/shoppingcart/ShoppingCart.java | 2 +- .../shoppinglist/ShoppingListEvents.java | 24 ++ .../src/org/ofbiz/entity/Delegator.java | 125 +++++- .../org/ofbiz/entity/GenericDelegator.java | 384 ++++++++++++++++++ .../ofbiz/entity/datasource/GenericDAO.java | 314 ++++++++++++++ .../entity/datasource/GenericHelper.java | 33 ++ .../entity/datasource/GenericHelperDAO.java | 43 ++ 7 files changed, 923 insertions(+), 2 deletions(-) diff --git a/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java b/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java index a857b46117d..3a1c1f1271a 100644 --- a/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java +++ b/applications/order/src/org/ofbiz/order/shoppingcart/ShoppingCart.java @@ -1432,7 +1432,7 @@ public void clear() { // clear the list if (autoSaveListId != null) { try { - org.ofbiz.order.shoppinglist.ShoppingListEvents.clearListInfo(this.getDelegator(), autoSaveListId); + org.ofbiz.order.shoppinglist.ShoppingListEvents.clearListInfoBatch(this.getDelegator(), autoSaveListId); } catch (GenericEntityException e) { Debug.logError(e, module); } diff --git a/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListEvents.java b/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListEvents.java index 2ae2de8f1fa..1c328369040 100644 --- a/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListEvents.java +++ b/applications/order/src/org/ofbiz/order/shoppinglist/ShoppingListEvents.java @@ -42,6 +42,8 @@ import org.ofbiz.entity.Delegator; import org.ofbiz.entity.GenericEntityException; import org.ofbiz.entity.GenericValue; +import org.ofbiz.entity.condition.EntityCondition; +import org.ofbiz.entity.model.ModelEntity; import org.ofbiz.entity.util.EntityQuery; import org.ofbiz.entity.util.EntityUtil; import org.ofbiz.order.shoppingcart.CartItemModifyException; @@ -546,6 +548,28 @@ public static int clearListInfo(Delegator delegator, String shoppingListId) thro // next remove the items return delegator.removeByAnd("ShoppingListItem", UtilMisc.toMap("shoppingListId", shoppingListId)); } + + /** + * Remove all items from the given list by batch. + */ + public static int clearListInfoBatch(Delegator delegator, String shoppingListId) throws GenericEntityException { + // remove the survey responses first + ModelEntity shoppingListItemSurveyModelEntity = delegator.getModelReader().getModelEntity("ShoppingListItemSurvey"); + List toBeRemovedCondition = new LinkedList(); + EntityCondition condition = EntityCondition.makeCondition(UtilMisc.toMap("shoppingListId", shoppingListId)); + toBeRemovedCondition.add(condition); + delegator.removeAllByAndBatch(shoppingListItemSurveyModelEntity, toBeRemovedCondition); + + // next remove the items + delegator.removeByAnd("ShoppingListItem", UtilMisc.toMap("shoppingListId", shoppingListId)); + ModelEntity shoppingListItemModelEntity = delegator.getModelReader().getModelEntity("ShoppingListItemSurvey"); + List toBeRemovedShoppingListItemCondition = new LinkedList(); + EntityCondition shoppingListItemCondition = EntityCondition.makeCondition(UtilMisc.toMap("shoppingListId", shoppingListId)); + toBeRemovedShoppingListItemCondition.add(shoppingListItemCondition); + return delegator.removeAllByAndBatch(shoppingListItemModelEntity, toBeRemovedShoppingListItemCondition); + } + + /** * Creates records for survey responses on survey items diff --git a/framework/entity/src/org/ofbiz/entity/Delegator.java b/framework/entity/src/org/ofbiz/entity/Delegator.java index 127fc53af63..ec4c47da2a7 100644 --- a/framework/entity/src/org/ofbiz/entity/Delegator.java +++ b/framework/entity/src/org/ofbiz/entity/Delegator.java @@ -913,5 +913,128 @@ enum OperationType {INSERT, UPDATE, DELETE} * Get use of Distributed Cache Clear mechanism status * @return boolean true if this delegator uses a Distributed Cache Clear mechanism */ - boolean useDistributedCacheClear(); + boolean useDistributedCacheClear(); + + /** + * Store the Entities from the List GenericValue instances to the persistent + * store.
This is different than the normal store method in that the + * store method only does an update, while the storeAll method checks to see + * if each entity exists, then either does an insert or an update as + * appropriate.
These updates all happen in one transaction, so they + * will either all succeed or all fail, if the data source supports + * transactions. This is just like to othersToStore feature of the + * GenericEntity on a create or store.
This is defferent from the normal + * storeAll method in that the store method use jdbc batch does updates or inserts. + * + * @param values + * List of GenericValue instances containing the entities to + * store + * @return int representing number of rows effected by this operation + */ + public int storeAllBatch(List toBeStored) throws GenericEntityException; + + /** + * Store the Entities from the List GenericValue instances to the persistent + * store.
This is different than the normal store method in that the + * store method only does an update, while the storeAll method checks to see + * if each entity exists, then either does an insert or an update as + * appropriate.
These updates all happen in one transaction, so they + * will either all succeed or all fail, if the data source supports + * transactions. This is just like to othersToStore feature of the + * GenericEntity on a create or store.
This is defferent from the normal + * storeAll method in that the store method use jdbc batch does updates or inserts. + * + * @param values + * List of GenericValue instances containing the entities to + * store + * @param doCacheClear + * boolean that specifies whether or not to automatically clear + * cache entries related to this operation. This should always be + * true - otherwise you will lose data integrity. + * @return int representing number of rows effected by this operation + */ + public int storeAllBatch(List toBeStored,boolean doCacheClear) throws GenericEntityException; + + /** + * Store the Entities from the List GenericValue instances to the persistent + * store.
This is different than the normal store method in that the + * store method only does an update, while the storeAll method checks to see + * if each entity exists, then either does an insert or an update as + * appropriate.
These updates all happen in one transaction, so they + * will either all succeed or all fail, if the data source supports + * transactions. This is just like to othersToStore feature of the + * GenericEntity on a create or store.
This is defferent from the normal + * storeAll method in that the store method use jdbc batch does updates or inserts. + * + * @param values + * List of GenericValue instances containing the entities to + * store + * @param doCacheClear + * boolean that specifies whether or not to automatically clear + * cache entries related to this operation. This should always be + * true - otherwise you will lose data integrity. + * @param createDummyFks + * boolean that specifies whether or not to automatically create + * "dummy" place holder FKs + * @return int representing number of rows effected by this operation + */ + public int storeAllBatch(List toBeStored,boolean doCacheClear ,boolean createDummyFks) throws GenericEntityException; + + + /** + * Remove the Entities from the List GenericValue instances to the persistent + * store. + * + * @param toBeRemoved + * List of GenericEntity instances containing the primary key of the entity list to remove. + * @return int representing number of rows effected by this operation + */ + public int removeAllByPrimaryKeyBatch(List toBeRemoved) throws GenericEntityException; + + + /** + * Remove the Entities from the List EntityCondition instances to the persistent + * store. + * + * @param modelEntity + * The modelEntity of the entity list to remove. + * @param toBeRemovedCondition + * List of EntityCondition instances containing the condition of the entity list to remove. + * @return int representing number of rows effected by this operation + */ + public int removeAllByAndBatch(ModelEntity modelEntity, List toBeRemovedCondition) throws GenericEntityException; + + /** + * Remove the Entities from the List GenericValue instances to the persistent + * store. + * + * @param toBeRemoved + * List of GenericEntity instances containing the primary key of the entity list to remove. + * @param doCacheClear + * boolean that specifies whether or not to automatically clear + * cache entries related to this operation. This should always be + * true - otherwise you will lose data integrity. + * + * @return int representing number of rows effected by this operation + */ + public int removeAllByPrimaryKeyBatch(List toBeRemoved,boolean doCacheClear) throws GenericEntityException; + + /** + * Remove the Entities from the List GenericValue instances to the persistent + * store. + * + * @param modelEntity + * The modelEntity of the entity list to remove. + * @param toBeRemovedCondition + * List of EntityCondition instances containing the condition of the entity list to remove. + * @param doCacheClear + * boolean that specifies whether or not to automatically clear + * cache entries related to this operation. This should always be + * true - otherwise you will lose data integrity. + * + * @return int representing number of rows effected by this operation + */ + public int removeAllByAndBatch(ModelEntity modelEntity, List toBeRemovedCondition,boolean doCacheClear) throws GenericEntityException; + + } diff --git a/framework/entity/src/org/ofbiz/entity/GenericDelegator.java b/framework/entity/src/org/ofbiz/entity/GenericDelegator.java index cc1d65bb877..860c1616858 100644 --- a/framework/entity/src/org/ofbiz/entity/GenericDelegator.java +++ b/framework/entity/src/org/ofbiz/entity/GenericDelegator.java @@ -2699,4 +2699,388 @@ public String getCurrentUserIdentifier() { List curValList = getUserIdentifierStack(); return curValList.size() > 0 ? curValList.get(0) : null; } + + /* (non-Javadoc) + * @see org.ofbiz.entity.Delegator#storeAllBatch(java.util.List,boolean) + */ + @Override + public int storeAllBatch(List toBeStored, boolean doCacheClear) throws GenericEntityException { + return storeAllBatch(toBeStored, true,false); + } + + /* (non-Javadoc) + * @see org.ofbiz.entity.Delegator#storeAllBatch(java.util.List) + */ + @Override + public int storeAllBatch(List toBeStored) throws GenericEntityException { + return storeAllBatch(toBeStored, true); + } + + /* (non-Javadoc) + * @see org.ofbiz.entity.Delegator#storeAllBatch(java.util.List,boolean,boolean) + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public int storeAllBatch(List toBeStored, boolean doCacheClear, boolean createDummyFks) + throws GenericEntityException { + if (toBeStored == null) { + return 0; + } + + int numberChanged = 0; + boolean beganTransaction = false; + try { + beganTransaction = TransactionUtil.begin(); + Map batchMap = new HashMap<>(); + + for (GenericValue value: toBeStored) { + String entityName = value.getEntityName(); + GenericPK primaryKey = value.getPrimaryKey(); +// GenericHelper helper = GenericHelperFactory.getHelper(helperInfo); + String groupName = getEntityGroupName(entityName); + GenericHelper helper = null; + List addStoreList = null; + List udpateStoreList = null; + if(! batchMap.containsKey(entityName)){ + helper = GenericHelperFactory.getHelper(getGroupHelperInfo(groupName)); + addStoreList = new LinkedList<>(); + udpateStoreList = new LinkedList<>(); + Map groupMap = new HashMap<>(); + groupMap.put("helper", helper); + groupMap.put("addStoreList", addStoreList); + groupMap.put("udpateStoreList", udpateStoreList); + batchMap.put(entityName, groupMap); + }else{ + helper = (GenericHelper) batchMap.get(entityName).get("helper"); + addStoreList = ( List) batchMap.get(entityName).get("addStoreList"); + udpateStoreList = ( List) batchMap.get(entityName).get("udpateStoreList"); + } + + // exists? + // NOTE: don't use findByPrimaryKey because we don't want to the ECA events to fire and such + if (!primaryKey.isPrimaryKey()) { + throw new GenericModelException("[GenericDelegator.storeAllBatch] One of the passed primary keys is not a valid primary key: " + primaryKey); + } + GenericValue existing = null; + try { + existing = helper.findByPrimaryKey(primaryKey); + } catch (GenericEntityNotFoundException e) { + existing = null; + } + + if (existing == null) { + if (createDummyFks) { + value.checkFks(true); + } + //this.create(value, doCacheClear); + addStoreList.add(value); + numberChanged++; + } else { + // don't send fields that are the same, and if no fields have changed, update nothing + ModelEntity modelEntity = value.getModelEntity(); + GenericValue toStore = GenericValue.create(this, modelEntity, value.getPrimaryKey()); + boolean atLeastOneField = false; + Iterator nonPksIter = modelEntity.getNopksIterator(); + while (nonPksIter.hasNext()) { + ModelField modelField = nonPksIter.next(); + String fieldName = modelField.getName(); + if (value.containsKey(fieldName)) { + Object fieldValue = value.get(fieldName); + Object oldValue = existing.get(fieldName); + if (!UtilObject.equalsHelper(oldValue, fieldValue)) { + toStore.put(fieldName, fieldValue); + atLeastOneField = true; + } + } + } + + if (atLeastOneField) { + if (createDummyFks) { + value.checkFks(true); + } + udpateStoreList.add(toStore); + //numberChanged += this.store(toStore, doCacheClear); + } + } + } + + try { + + for(String entityName : batchMap.keySet()){ + GenericHelper helper = (GenericHelper) batchMap.get(entityName).get("helper"); + List addStoreList = ( List) batchMap.get(entityName).get("addStoreList"); + List udpateStoreList = ( List) batchMap.get(entityName).get("udpateStoreList"); + + EntityEcaRuleRunner ecaRunner = this.getEcaRuleRunner(entityName); + for( GenericValue value :addStoreList){ + ecaRunner.evalRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_CREATE, value, false); + ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_CREATE, value, false); + if (value.getModelEntity().getHasFieldWithAuditLog()) { + createEntityAuditLogAll(value, true, false); + } + } + + + if(UtilValidate.isNotEmpty(addStoreList)){ + helper.create(this,addStoreList); + } + for( GenericValue value :addStoreList){ + ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_CREATE, value, false); + if (doCacheClear) { + ecaRunner.evalRules(EntityEcaHandler.EV_CACHE_CLEAR, EntityEcaHandler.OP_CREATE, value, false); + this.clearCacheLine(value); + } + if (testMode) { + GenericValue updatedEntity = this.findOne(value.getEntityName(), value.getPrimaryKey(), false); + storeForTestRollback(new TestOperation(OperationType.INSERT, updatedEntity)); + } + + } + + + for( GenericValue value :udpateStoreList){ + ecaRunner.evalRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_STORE, value, false); + ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_STORE, value, false); + if (value.getModelEntity().getHasFieldWithAuditLog()) { + createEntityAuditLogAll(value, true, false); + } + } + + + if(UtilValidate.isNotEmpty(udpateStoreList)){ + helper.store(this,udpateStoreList); + } + + for( GenericValue value :udpateStoreList){ + ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_STORE, value, false); + if (doCacheClear) { + ecaRunner.evalRules(EntityEcaHandler.EV_CACHE_CLEAR, EntityEcaHandler.OP_STORE, value, false); + this.clearCacheLine(value); + } + if (testMode) { + GenericValue updatedEntity = this.findOne(value.getEntityName(), value.getPrimaryKey(), false); + storeForTestRollback(new TestOperation(OperationType.UPDATE, updatedEntity)); + } + } + + } + + } catch (Exception e) { + Debug.logError(e, "Failure in storeAll storeAllBatch", module); + throw new GenericEntityException(e); + } + + + TransactionUtil.commit(beganTransaction); + return numberChanged; + } catch (Exception e) { + String errMsg = "Failure in storeAll operation: " + e.toString() + ". Rolling back transaction."; + Debug.logError(e, errMsg, module); + TransactionUtil.rollback(beganTransaction, errMsg, e); + throw new GenericEntityException(e); + } + } + + + /* (non-Javadoc) + * @see org.ofbiz.entity.Delegator#removeAllByPrimaryKeyBatch(java.util.List) + */ + @Override + public int removeAllByPrimaryKeyBatch(List toBeRemoved) throws GenericEntityException { + return removeAllByPrimaryKeyBatch(toBeRemoved,true); + } + + + /* (non-Javadoc) + * @see org.ofbiz.entity.Delegator#removeAllByAndBatch(ModelEntity,java.util.List) + */ + @Override + public int removeAllByAndBatch(ModelEntity modelEntity, List toBeRemovedCondition) + throws GenericEntityException { + return removeAllByAndBatch(modelEntity,toBeRemovedCondition,true); + } + + /* (non-Javadoc) + * @see org.ofbiz.entity.Delegator#removeAllByPrimaryKeyBatch(java.util.List,boolean) + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public int removeAllByPrimaryKeyBatch(List toBeRemoved, boolean doCacheClear) + throws GenericEntityException { + + if (toBeRemoved == null) { + return 0; + } + + int numberChanged = 0; + + boolean beganTransaction = false; + try { + + beganTransaction = TransactionUtil.begin(); + Map batchMap = new HashMap<>(); + + for (GenericEntity value: toBeRemoved) { + String entityName = value.getEntityName(); + String groupName = getEntityGroupName(entityName); + GenericHelper helper = null; + List delStoreList = null; + if(! batchMap.containsKey(entityName)){ + helper = GenericHelperFactory.getHelper(getGroupHelperInfo(groupName)); + delStoreList = new LinkedList<>(); + Map groupMap = new HashMap<>(); + groupMap.put("helper", helper); + groupMap.put("delStoreList", delStoreList); + batchMap.put(entityName, groupMap); + }else{ + helper = (GenericHelper) batchMap.get(entityName).get("helper"); + delStoreList = ( List) batchMap.get(entityName).get("delStoreList"); + } + delStoreList.add(value) ; + } + + try { + + for(String entityName : batchMap.keySet()){ + GenericHelper helper = (GenericHelper) batchMap.get(entityName).get("helper"); + List delStoreList = ( List) batchMap.get(entityName).get("delStoreList"); + if(UtilValidate.isNotEmpty(delStoreList)){ + EntityEcaRuleRunner ecaRunner = this.getEcaRuleRunner(entityName); + for( GenericEntity value :delStoreList){ + + ecaRunner.evalRules(EntityEcaHandler.EV_VALIDATE, EntityEcaHandler.OP_REMOVE, value.getPrimaryKey(), false); + ecaRunner.evalRules(EntityEcaHandler.EV_RUN, EntityEcaHandler.OP_REMOVE, value.getPrimaryKey(), false); + // if audit log on for any fields, save old value before removing so it's still there + if (value.getPrimaryKey().getModelEntity().getHasFieldWithAuditLog()) { + createEntityAuditLogAll(this.findOne(value.getEntityName(), value.getPrimaryKey(), false), true, true); + } + } + + helper.removeAllByPrimaryKey(this,delStoreList); + + for( GenericEntity value :delStoreList){ + GenericPK primaryKey = value.getPrimaryKey(); + GenericValue removedEntity = null; + if (testMode) { + removedEntity = this.findOne(primaryKey.getEntityName(), primaryKey, false); + } + if (doCacheClear) { + ecaRunner.evalRules(EntityEcaHandler.EV_CACHE_CLEAR, EntityEcaHandler.OP_REMOVE, primaryKey, false); + this.clearCacheLine(primaryKey); + } + this.saveEntitySyncRemoveInfo(primaryKey); + if (testMode) { + if (removedEntity != null) { + storeForTestRollback(new TestOperation(OperationType.DELETE, removedEntity)); + } + } + ecaRunner.evalRules(EntityEcaHandler.EV_RETURN, EntityEcaHandler.OP_REMOVE, primaryKey, false); + } + + } + } + + } catch (Exception e) { + Debug.logError(e, "Failure in removeAllByPrimaryKey", module); + throw new GenericEntityException(e); + } + + + TransactionUtil.commit(beganTransaction); + return numberChanged; + } catch (Exception e) { + String errMsg = "Failure in removeAllByPrimaryKey operation: " + e.toString() + ". Rolling back transaction."; + Debug.logError(e, errMsg, module); + TransactionUtil.rollback(beganTransaction, errMsg, e); + throw new GenericEntityException(e); + } + + } + + + /* (non-Javadoc) + * @see org.ofbiz.entity.Delegator#removeAllByAndBatch(ModelEntity,java.util.List,boolean) + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public int removeAllByAndBatch(ModelEntity modelEntity, List toBeRemovedCondition, + boolean doCacheClear) throws GenericEntityException { + + if (toBeRemovedCondition == null) { + return 0; + } + + int numberChanged = 0; + + boolean beganTransaction = false; + try { + + beganTransaction = TransactionUtil.begin(); + Map batchMap = new HashMap<>(); + + for (EntityCondition value: toBeRemovedCondition) { + String entityName = modelEntity.getEntityName(); + String groupName = getEntityGroupName(entityName); + GenericHelper helper = null; + List delStoreList = null; + if(! batchMap.containsKey(entityName)){ + helper = GenericHelperFactory.getHelper(getGroupHelperInfo(groupName)); + delStoreList = new LinkedList<>(); + Map groupMap = new HashMap<>(); + groupMap.put("helper", helper); + groupMap.put("delStoreList", delStoreList); + batchMap.put(entityName, groupMap); + }else{ + helper = (GenericHelper) batchMap.get(entityName).get("helper"); + delStoreList = ( List) batchMap.get(entityName).get("delStoreList"); + } + + delStoreList.add(value) ; + + } + + try { + + for(String entityName : batchMap.keySet()){ + GenericHelper helper = (GenericHelper) batchMap.get(entityName).get("helper"); + List delStoreList = ( List) batchMap.get(entityName).get("delStoreList"); + + if(UtilValidate.isNotEmpty(delStoreList)){ + + numberChanged = helper.removeAllByAnd(this,modelEntity,delStoreList); + if (numberChanged > 0 && doCacheClear) { + this.clearCacheLine(entityName); + } + + if (testMode) { + for (EntityCondition condition : delStoreList) { + List removedEntities = this.findList(entityName, condition, null, null, + null, false); + for (GenericValue entity : removedEntities) { + storeForTestRollback(new TestOperation(OperationType.DELETE, entity)); + } + } + } + } + + } + + } catch (Exception e) { + Debug.logError(e, "保存失败", module); + throw new GenericEntityException(e); + } + + + TransactionUtil.commit(beganTransaction); + return numberChanged; + } catch (Exception e) { + String errMsg = "Failure in storeAll operation: " + e.toString() + ". Rolling back transaction."; + Debug.logError(e, errMsg, module); + TransactionUtil.rollback(beganTransaction, errMsg, e); + throw new GenericEntityException(e); + } + + } + + } diff --git a/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java b/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java index c7e41a189b0..433de2d3fb6 100644 --- a/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java +++ b/framework/entity/src/org/ofbiz/entity/datasource/GenericDAO.java @@ -18,6 +18,7 @@ *******************************************************************************/ package org.ofbiz.entity.datasource; +import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; @@ -34,6 +35,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.UtilGenerics; import org.ofbiz.base.util.UtilValidate; import org.ofbiz.entity.Delegator; import org.ofbiz.entity.EntityLockedException; @@ -50,10 +52,12 @@ import org.ofbiz.entity.config.model.Datasource; import org.ofbiz.entity.config.model.EntityConfig; import org.ofbiz.entity.jdbc.DatabaseUtil; +import org.ofbiz.entity.jdbc.JdbcValueHandler; import org.ofbiz.entity.jdbc.SQLProcessor; import org.ofbiz.entity.jdbc.SqlJdbcUtil; import org.ofbiz.entity.model.ModelEntity; import org.ofbiz.entity.model.ModelField; +import org.ofbiz.entity.model.ModelFieldType; import org.ofbiz.entity.model.ModelFieldTypeReader; import org.ofbiz.entity.model.ModelKeyMap; import org.ofbiz.entity.model.ModelRelation; @@ -1229,4 +1233,314 @@ public List induceModelFromDb(Collection messages) { DatabaseUtil dbUtil = new DatabaseUtil(this.helperInfo); return dbUtil.induceModelFromDb(messages); } + + public int update(Delegator delegator,List values) throws GenericEntityException, SQLException { + SQLProcessor sqlP = new SQLProcessor(delegator,helperInfo); + int retVal = 0; + PreparedStatement ps = null; + List partialFields = null ; + for(int x = 0; x < values.size(); x++){ + GenericValue value = values.get(x); + ModelEntity modelEntity = value.getModelEntity(); + if (modelEntity == null) { + throw new GenericModelException("Could not find ModelEntity record for entityName: " + value.getEntityName()); + } + if(x == 0){ + // we don't want to update ALL fields, just the nonpk fields that are in the passed GenericEntity + partialFields = new LinkedList(); + Collection keys = value.getAllKeys(); + + Iterator nopkIter = modelEntity.getNopksIterator(); + while (nopkIter.hasNext()) { + ModelField curField = nopkIter.next(); + if (keys.contains(curField.getName())) { + partialFields.add(curField); + } + } + + //return customUpdate(value, modelEntity, partialFields); + if (modelEntity instanceof ModelViewEntity) { + singleUpdateView(value, (ModelViewEntity) modelEntity, partialFields, sqlP); + } + + // no non-primaryKey fields, update doesn't make sense, so don't do it + if (partialFields.size() <= 0) { + if (Debug.verboseOn()) Debug.logVerbose("Trying to do an update on an entity with no non-PK fields, returning having done nothing; entity=" + value, module); + // returning one because it was effectively updated, ie the same thing, so don't trigger any errors elsewhere + return 1; + } + + if (modelEntity.lock()) { + GenericEntity entityCopy = GenericEntity.createGenericEntity(value); + + select(entityCopy, sqlP); + Object stampField = value.get(ModelEntity.STAMP_FIELD); + + if ((stampField != null) && (!stampField.equals(entityCopy.get(ModelEntity.STAMP_FIELD)))) { + String lockedTime = entityCopy.getTimestamp(ModelEntity.STAMP_FIELD).toString(); + + throw new EntityLockedException("You tried to update an old version of this data. Version locked: (" + lockedTime + ")"); + } + } + + // if we have a STAMP_TX_FIELD then set it with NOW, always do this before the STAMP_FIELD + // NOTE: these fairly complicated if statements have a few objectives: + // 1. don't run the TransationUtil.getTransaction*Stamp() methods when we don't need to + // 2. don't set the stamp values if it is from an EntitySync (ie maintain original values), unless the stamps are null then set it anyway, ie even if it was from an EntitySync (also used for imports and such) + if (modelEntity.isField(ModelEntity.STAMP_TX_FIELD) && (!value.getIsFromEntitySync() || value.get(ModelEntity.STAMP_TX_FIELD) == null)) { + value.set(ModelEntity.STAMP_TX_FIELD, TransactionUtil.getTransactionStartStamp()); + addFieldIfMissing(partialFields, ModelEntity.STAMP_TX_FIELD, modelEntity); + } + + // if we have a STAMP_FIELD then update it with NOW. + if (modelEntity.isField(ModelEntity.STAMP_FIELD) && (!value.getIsFromEntitySync() || value.get(ModelEntity.STAMP_FIELD) == null)) { + value.set(ModelEntity.STAMP_FIELD, TransactionUtil.getTransactionUniqueNowStamp()); + addFieldIfMissing(partialFields, ModelEntity.STAMP_FIELD, modelEntity); + } + + StringBuilder sql = new StringBuilder().append("UPDATE ").append(modelEntity.getTableName(datasource)).append(" SET "); + modelEntity.colNameString(partialFields, sql, "", "=?, ", "=?", false); + sql.append(" WHERE "); + SqlJdbcUtil.makeWhereStringFromFields(sql, modelEntity.getPkFieldsUnmodifiable(), value, "AND"); + sqlP.prepareStatement(sql.toString()); + } + int i = 1; + ps = sqlP.getPreparedStatement(); + for (; i <= partialFields.size(); i++) { + ModelField curField = partialFields.get(i-1); + ModelFieldType mft = modelFieldTypeReader.getModelFieldType(curField.getType()); + JdbcValueHandler handler = UtilGenerics.cast(mft.getJdbcValueHandler()); + Object fieldValue = value.dangerousGetNoCheckButFast(curField); + if(UtilValidate.isNotEmpty(fieldValue)){ + handler.setValue(ps, i, fieldValue); + }else{ + handler.setValue(ps, i, fieldValue); + } + } + Iterator pksIter = modelEntity.getPksIterator(); + while (pksIter.hasNext()) { + ModelField curField = pksIter.next(); + ModelFieldType mft = modelFieldTypeReader.getModelFieldType(curField.getType()); + JdbcValueHandler handler = UtilGenerics.cast(mft.getJdbcValueHandler()); + Object fieldValue = value.dangerousGetNoCheckButFast(curField); + // for where clause variables only setValue if not null... + if (UtilValidate.isNotEmpty(fieldValue)) { + handler.setValue(ps, i, fieldValue); + } + i++; + } + ps.addBatch(); + value.synchronizedWithDatasource(); + } + + try { + int[] count = sqlP.getPreparedStatement().executeBatch(); + for (int i : count) { + retVal = retVal + i; + } + } finally { + sqlP.close(); + } + if (retVal == 0) { + throw new GenericEntityNotFoundException("Tried to update an entity that does not exist, entity list: " + values.toString()); + } + return retVal; + } + + public int create(Delegator delegator,List values) throws GenericEntityException, SQLException { + SQLProcessor sqlP = new SQLProcessor(delegator,helperInfo); + int retVal = 0; + List fieldsToSave = null; + PreparedStatement ps = null; + for(int x = 0; x < values.size(); x++){ + GenericValue value = values.get(x); + if(UtilValidate.isEmpty(value)){ + throw new GenericEntityNotFoundException("Tried to update an entity that does not exist, entity list: " + value.toString()); + } + if(x ==0){ + ModelEntity modelEntity = value.getModelEntity(); + if (modelEntity == null) { + throw new GenericModelException("Could not find ModelEntity record for entityName: " + value.getEntityName()); + } + fieldsToSave = modelEntity.getFieldsUnmodifiable(); + if (modelEntity instanceof ModelViewEntity) { + singleUpdateView(value, (ModelViewEntity) modelEntity,fieldsToSave , sqlP); + } + + // if we have a STAMP_TX_FIELD or CREATE_STAMP_TX_FIELD then set it with NOW, always do this before the STAMP_FIELD + // NOTE: these fairly complicated if statements have a few objectives: + // 1. don't run the TransationUtil.getTransaction*Stamp() methods when we don't need to + // 2. don't set the stamp values if it is from an EntitySync (ie maintain original values), unless the stamps are null then set it anyway, ie even if it was from an EntitySync (also used for imports and such) + boolean stampTxIsField = modelEntity.isField(ModelEntity.STAMP_TX_FIELD); + boolean createStampTxIsField = modelEntity.isField(ModelEntity.CREATE_STAMP_TX_FIELD); + if ((stampTxIsField || createStampTxIsField) && (!value.getIsFromEntitySync() || (stampTxIsField && value.get(ModelEntity.STAMP_TX_FIELD) == null) || (createStampTxIsField && value.get(ModelEntity.CREATE_STAMP_TX_FIELD) == null))) { + Timestamp txStartStamp = TransactionUtil.getTransactionStartStamp(); + if (stampTxIsField && (!value.getIsFromEntitySync() || value.get(ModelEntity.STAMP_TX_FIELD) == null)) { + value.set(ModelEntity.STAMP_TX_FIELD, txStartStamp); + addFieldIfMissing(fieldsToSave, ModelEntity.STAMP_TX_FIELD, modelEntity); + } + if (createStampTxIsField && (!value.getIsFromEntitySync() || value.get(ModelEntity.CREATE_STAMP_TX_FIELD) == null)) { + value.set(ModelEntity.CREATE_STAMP_TX_FIELD, txStartStamp); + addFieldIfMissing(fieldsToSave, ModelEntity.CREATE_STAMP_TX_FIELD, modelEntity); + } + } + + // if we have a STAMP_FIELD or CREATE_STAMP_FIELD then set it with NOW + boolean stampIsField = modelEntity.isField(ModelEntity.STAMP_FIELD); + boolean createStampIsField = modelEntity.isField(ModelEntity.CREATE_STAMP_FIELD); + if ((stampIsField || createStampIsField) && (!value.getIsFromEntitySync() || (stampIsField && value.get(ModelEntity.STAMP_FIELD) == null) || (createStampIsField && value.get(ModelEntity.CREATE_STAMP_FIELD) == null))) { + Timestamp startStamp = TransactionUtil.getTransactionUniqueNowStamp(); + if (stampIsField && (!value.getIsFromEntitySync() || value.get(ModelEntity.STAMP_FIELD) == null)) { + value.set(ModelEntity.STAMP_FIELD, startStamp); + addFieldIfMissing(fieldsToSave, ModelEntity.STAMP_FIELD, modelEntity); + } + if (createStampIsField && (!value.getIsFromEntitySync() || value.get(ModelEntity.CREATE_STAMP_FIELD) == null)) { + value.set(ModelEntity.CREATE_STAMP_FIELD, startStamp); + addFieldIfMissing(fieldsToSave, ModelEntity.CREATE_STAMP_FIELD, modelEntity); + } + } + + StringBuilder sqlB = new StringBuilder("INSERT INTO ").append(modelEntity.getTableName(datasource)).append(" ("); + + modelEntity.colNameString(fieldsToSave, sqlB, ""); + sqlB.append(") VALUES ("); + modelEntity.fieldsStringList(fieldsToSave, sqlB, "?", ", "); + String sql = sqlB.append(")").toString(); + sqlP.prepareStatement(sql); + ps = sqlP.getPreparedStatement(); + + } + if(UtilValidate.isNotEmpty(ps)){ + int i = 1; + for (; i <= fieldsToSave.size(); i++) { + ModelField curField = fieldsToSave.get(i-1); + ModelFieldType mft = modelFieldTypeReader.getModelFieldType(curField.getType()); + JdbcValueHandler handler = UtilGenerics.cast(mft.getJdbcValueHandler()); + Object fieldValue = value.dangerousGetNoCheckButFast(curField); + if(UtilValidate.isNotEmpty(fieldValue)){ + handler.setValue(ps, i, fieldValue); + }else{ + handler.setValue(ps, i, fieldValue); + } + } + ps.addBatch(); + value.synchronizedWithDatasource(); + } + } + + try { + int[] count = sqlP.getPreparedStatement().executeBatch(); + for (int i : count) { + retVal = retVal + i; + } + } finally { + sqlP.close(); + } + if (retVal == 0) { + throw new GenericEntityNotFoundException("Tried to update an entity that does not exist, entity list: " + values.toString()); + } + return retVal; + } + + public int removeAllByAnd(Delegator delegator,ModelEntity modelEntity, List values) throws GenericEntityException, SQLException { + + SQLProcessor sqlP = new SQLProcessor(delegator,helperInfo); + int retVal = 0; + PreparedStatement ps = null; + for(int x = 0; x < values.size(); x++){ + EntityCondition value = values.get(x); + if (UtilValidate.isEmpty(value)) { + throw new GenericEntityNotFoundException("Tried to update an entity that does not exist, entity list: " + value.toString()); + } + if (modelEntity == null) { + throw new GenericModelException("Could not find ModelEntity record for entity"); + } + if (modelEntity instanceof ModelViewEntity) { + throw new org.ofbiz.entity.GenericNotImplementedException("Operation delete not supported yet for view entities"); + } + StringBuilder sql = new StringBuilder("DELETE FROM ").append(modelEntity.getTableName(this.datasource)); + String whereCondition = value.makeWhereString(modelEntity, null, this.datasource); + if (UtilValidate.isNotEmpty(whereCondition)) { + sql.append(" WHERE ").append(whereCondition); + } + if (x == 0) { + sqlP.prepareStatement(sql.toString()); + ps = sqlP.getPreparedStatement(); + }else{ + ps.addBatch(sql.toString()); + } + } + + try { + int[] count = sqlP.getPreparedStatement().executeBatch(); + for (int i : count) { + retVal = retVal + i; + } + } finally { + sqlP.close(); + } + if (retVal == 0) { + throw new GenericEntityNotFoundException("Tried to update an entity that does not exist, entity list: " + values.toString()); + } + return retVal; + + } + + public int removeAllByPrimaryKey(Delegator delegator,List values) throws GenericEntityException, SQLException { + SQLProcessor sqlP = new SQLProcessor(delegator,helperInfo); + int retVal = 0; + PreparedStatement ps = null; + for(int x = 0; x < values.size(); x++){ + GenericEntity value = values.get(x); + ModelEntity modelEntity = value.getModelEntity(); + if (x == 0) { + if (UtilValidate.isEmpty(value)) { + throw new GenericEntityNotFoundException("Tried to update an entity that does not exist, entity list: " + value.toString()); + } + if (modelEntity == null) { + throw new GenericModelException("Could not find ModelEntity record for entityName: " + value.getEntityName()); + } + if (modelEntity instanceof ModelViewEntity) { + throw new org.ofbiz.entity.GenericNotImplementedException("Operation delete not supported yet for view entities"); + } + StringBuilder sql = new StringBuilder().append("DELETE FROM ").append(modelEntity.getTableName(datasource)).append(" WHERE "); + SqlJdbcUtil.makeWhereStringFromFields(sql, modelEntity.getPkFieldsUnmodifiable(), value, "AND"); + sqlP.prepareStatement(sql.toString()); + ps = sqlP.getPreparedStatement(); + } + if(UtilValidate.isNotEmpty(ps)){ + int i = 1; + Iterator pksIter = modelEntity.getPksIterator(); + while (pksIter.hasNext()) { + ModelField curField = pksIter.next(); + ModelFieldType mft = modelFieldTypeReader.getModelFieldType(curField.getType()); + JdbcValueHandler handler = UtilGenerics.cast(mft.getJdbcValueHandler()); + Object fieldValue = value.dangerousGetNoCheckButFast(curField); + // for where clause variables only setValue if not null... + if (UtilValidate.isNotEmpty(fieldValue)) { + handler.setValue(ps, i, fieldValue); + } + i++; + } + ps.addBatch(); + } + } + + try { + int[] count = sqlP.getPreparedStatement().executeBatch(); + for (int i : count) { + retVal = retVal + i; + } + } finally { + sqlP.close(); + } + if (retVal == 0) { + throw new GenericEntityNotFoundException("Tried to update an entity that does not exist, entity list: " + values.toString()); + } + return retVal; + + } + + + } diff --git a/framework/entity/src/org/ofbiz/entity/datasource/GenericHelper.java b/framework/entity/src/org/ofbiz/entity/datasource/GenericHelper.java index 35d1e1f96b8..d3c0e9f7705 100644 --- a/framework/entity/src/org/ofbiz/entity/datasource/GenericHelper.java +++ b/framework/entity/src/org/ofbiz/entity/datasource/GenericHelper.java @@ -20,12 +20,15 @@ package org.ofbiz.entity.datasource; +import java.sql.SQLException; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import org.ofbiz.entity.Delegator; +import org.ofbiz.entity.GenericDelegator; +import org.ofbiz.entity.GenericEntity; import org.ofbiz.entity.GenericEntityException; import org.ofbiz.entity.GenericPK; import org.ofbiz.entity.GenericValue; @@ -125,4 +128,34 @@ public long findCountByCondition(Delegator delegator, ModelEntity modelEntity, E *@param addMissing Flag indicating whether or not to add missing entities and fields on the server */ public void checkDataSource(Map modelEntities, List messages, boolean addMissing) throws GenericEntityException; + + + /** Store the List of Entity from the GenericValue to the persistent store + *@param values GenericValue instance containing the entity + *@return int representing number of rows effected by this operation + */ + public int store(Delegator delegator,List values) throws GenericEntityException , SQLException; + + + /** Create the List of Entity from the GenericValue to the persistent store + *@param values GenericValue instance containing the entity + *@return int representing number of rows effected by this operation + */ + public int create(Delegator delegator,List values) throws GenericEntityException, SQLException; + + + /** Create the List of Entity from the GenericValue to the persistent store + *@param delStoreList GenericValue instance containing the entity + *@return int representing number of rows effected by this operation + */ + public int removeAllByPrimaryKey(Delegator delegator,List delStoreList)throws GenericEntityException , SQLException; + + + /** Removes/deletes Generic Entity records found by all the specified condition + *@param modelEntity The ModelEntity of the Entity as defined in the entity XML file + *@param delStoreList The condition that restricts the list of removed values + *@return int representing number of rows effected by this operation + */ + public int removeAllByAnd(Delegator delegator,ModelEntity modelEntity, List delStoreList)throws GenericEntityException , SQLException; + } diff --git a/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java b/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java index 1e79c8af8da..4df10ae0143 100644 --- a/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java +++ b/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java @@ -18,6 +18,7 @@ *******************************************************************************/ package org.ofbiz.entity.datasource; +import java.sql.SQLException; import java.util.Collection; import java.util.LinkedList; import java.util.List; @@ -26,6 +27,7 @@ import org.ofbiz.base.util.Debug; import org.ofbiz.entity.Delegator; +import org.ofbiz.entity.GenericEntity; import org.ofbiz.entity.GenericEntityException; import org.ofbiz.entity.GenericPK; import org.ofbiz.entity.GenericValue; @@ -194,4 +196,45 @@ public int storeByCondition(Delegator delegator, ModelEntity modelEntity, Map modelEntities, List messages, boolean addMissing) throws GenericEntityException { genericDAO.checkDb(modelEntities, messages, addMissing); } + + /** + * 增加JDBC批处理保存 + * + * Store the Entity from the GenericValue to the persistent store + *@param value GenericValue instance containing the entity + *@return int representing number of rows effected by this operation + *@throws GenericEntityException SQLException + */ + public int store(Delegator delegator, List values) throws GenericEntityException, SQLException { + if (values == null) { + return 0; + } + return genericDAO.update(delegator,values); + } + + @Override + public int create(Delegator delegator,List values) throws GenericEntityException, SQLException { + if (values == null) { + return 0; + } + return genericDAO.create(delegator,values); + } + + + @Override + public int removeAllByPrimaryKey(Delegator delegator,List delStoreList) throws GenericEntityException, SQLException { + if (delStoreList == null) { + return 0; + } + return genericDAO.removeAllByPrimaryKey(delegator,delStoreList); + } + + @Override + public int removeAllByAnd(Delegator delegator,ModelEntity modelEntity, List delStoreList) + throws GenericEntityException, SQLException { + if (delStoreList == null) { + return 0; + } + return genericDAO.removeAllByAnd(delegator,modelEntity,delStoreList); + } } From 95cdc9282fc3aed4eeeaae19f7b754461d5cd02c Mon Sep 17 00:00:00 2001 From: thanos Date: Mon, 2 May 2016 09:01:28 +0800 Subject: [PATCH 2/2] update delegator comments --- .../entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java | 1 - 1 file changed, 1 deletion(-) diff --git a/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java b/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java index 4df10ae0143..29667bd5afe 100644 --- a/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java +++ b/framework/entity/src/org/ofbiz/entity/datasource/GenericHelperDAO.java @@ -198,7 +198,6 @@ public void checkDataSource(Map modelEntities, List } /** - * 增加JDBC批处理保存 * * Store the Entity from the GenericValue to the persistent store *@param value GenericValue instance containing the entity