0001: /*
0002: * $Id: GenericDAO.java,v 1.15 2004/03/10 14:33:51 jonesde Exp $
0003: *
0004: * Copyright (c) 2001, 2002 The Open For Business Project - www.ofbiz.org
0005: *
0006: * Permission is hereby granted, free of charge, to any person obtaining a
0007: * copy of this software and associated documentation files (the "Software"),
0008: * to deal in the Software without restriction, including without limitation
0009: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0010: * and/or sell copies of the Software, and to permit persons to whom the
0011: * Software is furnished to do so, subject to the following conditions:
0012: *
0013: * The above copyright notice and this permission notice shall be included
0014: * in all copies or substantial portions of the Software.
0015: *
0016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
0017: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0018: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
0019: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
0020: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
0021: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
0022: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0023: *
0024: */
0025: package org.ofbiz.entity.datasource;
0026:
0027: import java.sql.ResultSet;
0028: import java.sql.SQLException;
0029: import java.sql.Timestamp;
0030: import java.util.*;
0031:
0032: import org.ofbiz.base.util.Debug;
0033: import org.ofbiz.base.util.UtilValidate;
0034: import org.ofbiz.entity.*;
0035: import org.ofbiz.entity.condition.EntityCondition;
0036: import org.ofbiz.entity.condition.EntityConditionParam;
0037: import org.ofbiz.entity.condition.EntityFieldMap;
0038: import org.ofbiz.entity.condition.EntityOperator;
0039: import org.ofbiz.entity.config.EntityConfigUtil;
0040: import org.ofbiz.entity.jdbc.DatabaseUtil;
0041: import org.ofbiz.entity.jdbc.SQLProcessor;
0042: import org.ofbiz.entity.jdbc.SqlJdbcUtil;
0043: import org.ofbiz.entity.model.ModelEntity;
0044: import org.ofbiz.entity.model.ModelField;
0045: import org.ofbiz.entity.model.ModelFieldTypeReader;
0046: import org.ofbiz.entity.model.ModelKeyMap;
0047: import org.ofbiz.entity.model.ModelRelation;
0048: import org.ofbiz.entity.model.ModelViewEntity;
0049: import org.ofbiz.entity.transaction.TransactionUtil;
0050: import org.ofbiz.entity.util.EntityFindOptions;
0051: import org.ofbiz.entity.util.EntityListIterator;
0052:
0053: /**
0054: * Generic Entity Data Access Object - Handles persisntence for any defined entity.
0055: *
0056: * @author <a href="mailto:jonesde@ofbiz.org">David E. Jones</a>
0057: * @author <a href="mailto:jaz@ofbiz.org">Andy Zeneski</a>
0058: * @author <a href="mailto:chris_maurer@altavista.com">Chris Maurer</a>
0059: * @author <a href="mailto:jdonnerstag@eds.de">Juergen Donnerstag</a>
0060: * @author <a href="mailto:gielen@aixcept.de">Rene Gielen</a>
0061: * @author <a href="mailto:john_nutting@telluridetechnologies.com">John Nutting</a>
0062: * @version $Revision: 1.15 $
0063: * @since 1.0
0064: */
0065: public class GenericDAO {
0066:
0067: public static final String module = GenericDAO.class.getName();
0068:
0069: protected static Map genericDAOs = new Hashtable();
0070: protected String helperName;
0071: protected ModelFieldTypeReader modelFieldTypeReader = null;
0072: protected EntityConfigUtil.DatasourceInfo datasourceInfo;
0073:
0074: public static GenericDAO getGenericDAO(String helperName) {
0075: GenericDAO newGenericDAO = (GenericDAO) genericDAOs
0076: .get(helperName);
0077:
0078: if (newGenericDAO == null) { // don't want to block here
0079: synchronized (GenericDAO.class) {
0080: newGenericDAO = (GenericDAO) genericDAOs
0081: .get(helperName);
0082: if (newGenericDAO == null) {
0083: newGenericDAO = new GenericDAO(helperName);
0084: genericDAOs.put(helperName, newGenericDAO);
0085: }
0086: }
0087: }
0088: return newGenericDAO;
0089: }
0090:
0091: public GenericDAO(String helperName) {
0092: this .helperName = helperName;
0093: this .modelFieldTypeReader = ModelFieldTypeReader
0094: .getModelFieldTypeReader(helperName);
0095: this .datasourceInfo = EntityConfigUtil
0096: .getDatasourceInfo(helperName);
0097: }
0098:
0099: private void addFieldIfMissing(List fieldsToSave, String fieldName,
0100: ModelEntity modelEntity) {
0101: Iterator fieldsToSaveIter = fieldsToSave.iterator();
0102: while (fieldsToSaveIter.hasNext()) {
0103: ModelField fieldToSave = (ModelField) fieldsToSaveIter
0104: .next();
0105: if (fieldName.equals(fieldToSave.getName())) {
0106: return;
0107: }
0108: }
0109: // at this point we didn't find it
0110: fieldsToSave.add(modelEntity.getField(fieldName));
0111: }
0112:
0113: public int insert(GenericEntity entity)
0114: throws GenericEntityException {
0115: ModelEntity modelEntity = entity.getModelEntity();
0116:
0117: if (modelEntity == null) {
0118: throw new GenericModelException(
0119: "Could not find ModelEntity record for entityName: "
0120: + entity.getEntityName());
0121: }
0122:
0123: SQLProcessor sqlP = new SQLProcessor(helperName);
0124:
0125: try {
0126: return singleInsert(entity, modelEntity, modelEntity
0127: .getFieldsCopy(), sqlP);
0128: } catch (GenericEntityException e) {
0129: sqlP.rollback();
0130: throw new GenericEntityException(
0131: "Exception while inserting the following entity: "
0132: + entity.toString(), e);
0133: } finally {
0134: sqlP.close();
0135: }
0136: }
0137:
0138: private int singleInsert(GenericEntity entity,
0139: ModelEntity modelEntity, List fieldsToSave,
0140: SQLProcessor sqlP) throws GenericEntityException {
0141: if (modelEntity instanceof ModelViewEntity) {
0142: return singleUpdateView(entity,
0143: (ModelViewEntity) modelEntity, fieldsToSave, sqlP);
0144: }
0145:
0146: // if we have a STAMP_TX_FIELD or CREATE_STAMP_TX_FIELD then set it with NOW, always do this before the STAMP_FIELD
0147: boolean stampTxIsField = modelEntity
0148: .isField(ModelEntity.STAMP_TX_FIELD);
0149: boolean createStampTxIsField = modelEntity
0150: .isField(ModelEntity.CREATE_STAMP_TX_FIELD);
0151: if ((stampTxIsField || createStampTxIsField)
0152: && !entity.getIsFromEntitySync()) {
0153: Timestamp txStartStamp = TransactionUtil
0154: .getTransactionStartStamp();
0155: if (stampTxIsField) {
0156: entity.set(ModelEntity.STAMP_TX_FIELD, txStartStamp);
0157: addFieldIfMissing(fieldsToSave,
0158: ModelEntity.STAMP_TX_FIELD, modelEntity);
0159: }
0160: if (createStampTxIsField) {
0161: entity.set(ModelEntity.CREATE_STAMP_TX_FIELD,
0162: txStartStamp);
0163: addFieldIfMissing(fieldsToSave,
0164: ModelEntity.CREATE_STAMP_TX_FIELD, modelEntity);
0165: }
0166: }
0167:
0168: // if we have a STAMP_FIELD or CREATE_STAMP_FIELD then set it with NOW
0169: boolean stampIsField = modelEntity
0170: .isField(ModelEntity.STAMP_FIELD);
0171: boolean createStampIsField = modelEntity
0172: .isField(ModelEntity.CREATE_STAMP_FIELD);
0173: if ((stampIsField || createStampIsField)
0174: && !entity.getIsFromEntitySync()) {
0175: Timestamp startStamp = TransactionUtil
0176: .getTransactionUniqueNowStamp();
0177: if (stampIsField) {
0178: entity.set(ModelEntity.STAMP_FIELD, startStamp);
0179: addFieldIfMissing(fieldsToSave,
0180: ModelEntity.STAMP_FIELD, modelEntity);
0181: }
0182: if (createStampIsField) {
0183: entity.set(ModelEntity.CREATE_STAMP_FIELD, startStamp);
0184: addFieldIfMissing(fieldsToSave,
0185: ModelEntity.CREATE_STAMP_FIELD, modelEntity);
0186: }
0187: }
0188:
0189: String sql = "INSERT INTO "
0190: + modelEntity.getTableName(datasourceInfo) + " ("
0191: + modelEntity.colNameString(fieldsToSave)
0192: + ") VALUES ("
0193: + modelEntity.fieldsStringList(fieldsToSave, "?", ", ")
0194: + ")";
0195:
0196: try {
0197: sqlP.prepareStatement(sql);
0198: SqlJdbcUtil.setValues(sqlP, fieldsToSave, entity,
0199: modelFieldTypeReader);
0200: int retVal = sqlP.executeUpdate();
0201:
0202: entity.synchronizedWithDatasource();
0203: return retVal;
0204: } catch (GenericEntityException e) {
0205: throw new GenericEntityException("while inserting: "
0206: + entity.toString(), e);
0207: } finally {
0208: sqlP.close();
0209: }
0210: }
0211:
0212: public int updateAll(GenericEntity entity)
0213: throws GenericEntityException {
0214: ModelEntity modelEntity = entity.getModelEntity();
0215:
0216: if (modelEntity == null) {
0217: throw new GenericModelException(
0218: "Could not find ModelEntity record for entityName: "
0219: + entity.getEntityName());
0220: }
0221:
0222: return customUpdate(entity, modelEntity, modelEntity
0223: .getNopksCopy());
0224: }
0225:
0226: public int update(GenericEntity entity)
0227: throws GenericEntityException {
0228: ModelEntity modelEntity = entity.getModelEntity();
0229:
0230: if (modelEntity == null) {
0231: throw new GenericModelException(
0232: "Could not find ModelEntity record for entityName: "
0233: + entity.getEntityName());
0234: }
0235:
0236: // we don't want to update ALL fields, just the nonpk fields that are in the passed GenericEntity
0237: List partialFields = new ArrayList();
0238: Collection keys = entity.getAllKeys();
0239:
0240: for (int fi = 0; fi < modelEntity.getNopksSize(); fi++) {
0241: ModelField curField = modelEntity.getNopk(fi);
0242: if (keys.contains(curField.getName())) {
0243: partialFields.add(curField);
0244: }
0245: }
0246:
0247: return customUpdate(entity, modelEntity, partialFields);
0248: }
0249:
0250: private int customUpdate(GenericEntity entity,
0251: ModelEntity modelEntity, List fieldsToSave)
0252: throws GenericEntityException {
0253: SQLProcessor sqlP = new SQLProcessor(helperName);
0254: try {
0255: return singleUpdate(entity, modelEntity, fieldsToSave, sqlP);
0256: } catch (GenericEntityException e) {
0257: sqlP.rollback();
0258: throw new GenericEntityException(
0259: "Exception while updating the following entity: "
0260: + entity.toString(), e);
0261: } finally {
0262: sqlP.close();
0263: }
0264: }
0265:
0266: private int singleUpdate(GenericEntity entity,
0267: ModelEntity modelEntity, List fieldsToSave,
0268: SQLProcessor sqlP) throws GenericEntityException {
0269: if (modelEntity instanceof ModelViewEntity) {
0270: return singleUpdateView(entity,
0271: (ModelViewEntity) modelEntity, fieldsToSave, sqlP);
0272: }
0273:
0274: // no non-primaryKey fields, update doesn't make sense, so don't do it
0275: if (fieldsToSave.size() <= 0) {
0276: if (Debug.verboseOn())
0277: Debug
0278: .logVerbose(
0279: "Trying to do an update on an entity with no non-PK fields, returning having done nothing; entity="
0280: + entity, module);
0281: // returning one because it was effectively updated, ie the same thing, so don't trigger any errors elsewhere
0282: return 1;
0283: }
0284:
0285: if (modelEntity.lock()) {
0286: GenericEntity entityCopy = new GenericEntity(entity);
0287:
0288: select(entityCopy, sqlP);
0289: Object stampField = entity.get(ModelEntity.STAMP_FIELD);
0290:
0291: if ((stampField != null)
0292: && (!stampField.equals(entityCopy
0293: .get(ModelEntity.STAMP_FIELD)))) {
0294: String lockedTime = entityCopy.getTimestamp(
0295: ModelEntity.STAMP_FIELD).toString();
0296:
0297: throw new EntityLockedException(
0298: "You tried to update an old version of this data. Version locked: ("
0299: + lockedTime + ")");
0300: }
0301: }
0302:
0303: // if we have a STAMP_TX_FIELD then set it with NOW, always do this before the STAMP_FIELD
0304: if (modelEntity.isField(ModelEntity.STAMP_TX_FIELD)
0305: && !entity.getIsFromEntitySync()) {
0306: entity.set(ModelEntity.STAMP_TX_FIELD, TransactionUtil
0307: .getTransactionStartStamp());
0308: addFieldIfMissing(fieldsToSave, ModelEntity.STAMP_TX_FIELD,
0309: modelEntity);
0310: }
0311:
0312: // if we have a STAMP_FIELD then update it with NOW.
0313: if (modelEntity.isField(ModelEntity.STAMP_FIELD)
0314: && !entity.getIsFromEntitySync()) {
0315: entity.set(ModelEntity.STAMP_FIELD, TransactionUtil
0316: .getTransactionUniqueNowStamp());
0317: addFieldIfMissing(fieldsToSave, ModelEntity.STAMP_FIELD,
0318: modelEntity);
0319: }
0320:
0321: String sql = "UPDATE "
0322: + modelEntity.getTableName(datasourceInfo)
0323: + " SET "
0324: + modelEntity.colNameString(fieldsToSave, "=?, ", "=?",
0325: false)
0326: + " WHERE "
0327: + SqlJdbcUtil.makeWhereStringFromFields(modelEntity
0328: .getPksCopy(), entity, "AND");
0329:
0330: int retVal = 0;
0331:
0332: try {
0333: sqlP.prepareStatement(sql);
0334: SqlJdbcUtil.setValues(sqlP, fieldsToSave, entity,
0335: modelFieldTypeReader);
0336: SqlJdbcUtil.setPkValues(sqlP, modelEntity, entity,
0337: modelFieldTypeReader);
0338: retVal = sqlP.executeUpdate();
0339: entity.synchronizedWithDatasource();
0340: } catch (GenericEntityException e) {
0341: throw new GenericEntityException("while updating: "
0342: + entity.toString(), e);
0343: } finally {
0344: sqlP.close();
0345: }
0346:
0347: if (retVal == 0) {
0348: throw new GenericEntityNotFoundException(
0349: "Tried to update an entity that does not exist.");
0350: }
0351: return retVal;
0352: }
0353:
0354: /** Store the passed entity - insert if does not exist, otherwise update */
0355: private int singleStore(GenericEntity entity, SQLProcessor sqlP)
0356: throws GenericEntityException {
0357: GenericPK tempPK = entity.getPrimaryKey();
0358: ModelEntity modelEntity = entity.getModelEntity();
0359:
0360: try {
0361: // must use same connection for select or it won't be in the same transaction...
0362: select(tempPK, sqlP);
0363: } catch (GenericEntityNotFoundException e) {
0364: // Debug.logInfo(e, module);
0365: // select failed, does not exist, insert
0366: return singleInsert(entity, modelEntity, modelEntity
0367: .getFieldsCopy(), sqlP);
0368: }
0369: // select did not fail, so exists, update
0370:
0371: List partialFields = new ArrayList();
0372: Collection keys = entity.getAllKeys();
0373:
0374: for (int fi = 0; fi < modelEntity.getNopksSize(); fi++) {
0375: ModelField curField = modelEntity.getNopk(fi);
0376:
0377: // we don't want to update ALL fields, just the nonpk fields that are in the passed GenericEntity
0378: if (keys.contains(curField.getName())) {
0379: //also, only update the fields that have changed, since we have the selected values in tempPK we can compare
0380: if (entity.get(curField.getName()) == null) {
0381: if (tempPK.get(curField.getName()) != null) {
0382: //entity field is null, tempPK is not so are different
0383: partialFields.add(curField);
0384: }
0385: } else if (!entity.get(curField.getName()).equals(
0386: tempPK.get(curField.getName()))) {
0387: //entity field is not null, and compared to tempPK field is different
0388: partialFields.add(curField);
0389: }
0390: }
0391: }
0392:
0393: return singleUpdate(entity, modelEntity, partialFields, sqlP);
0394: }
0395:
0396: public int storeAll(List entities) throws GenericEntityException {
0397: if (entities == null || entities.size() <= 0) {
0398: return 0;
0399: }
0400:
0401: SQLProcessor sqlP = new SQLProcessor(helperName);
0402: int totalStored = 0;
0403: try {
0404: Iterator entityIter = entities.iterator();
0405: while (entityIter != null && entityIter.hasNext()) {
0406: GenericEntity curEntity = (GenericEntity) entityIter
0407: .next();
0408: totalStored += singleStore(curEntity, sqlP);
0409: }
0410: } catch (GenericEntityException e) {
0411: sqlP.rollback();
0412: throw new GenericEntityException(
0413: "Exception occurred in storeAll", e);
0414: } finally {
0415: sqlP.close();
0416: }
0417: return totalStored;
0418: }
0419:
0420: /* ====================================================================== */
0421:
0422: /* ====================================================================== */
0423:
0424: /**
0425: * Try to update the given ModelViewEntity by trying to insert/update on the entities of which the view is composed.
0426: *
0427: * Works fine with standard O/R mapped models, but has some restrictions meeting more complicated view entities.
0428: * <li>A direct link is required, which means that one of the ModelViewLink field entries must have a value found
0429: * in the given view entity, for each ModelViewLink</li>
0430: * <li>For now, each member entity is updated iteratively, so if eg. the second member entity fails to update,
0431: * the first is written although. See code for details. Try to use "clean" views, until code is more robust ...</li>
0432: * <li>For now, aliased field names in views are not processed correctly, I guess. To be honest, I did not
0433: * find out how to construct such a view - so view fieldnames must have same named fields in member entities.</li>
0434: * <li>A new exception, e.g. GenericViewNotUpdatable, should be defined and thrown if the update fails</li>
0435: *
0436: */
0437: private int singleUpdateView(GenericEntity entity,
0438: ModelViewEntity modelViewEntity, List fieldsToSave,
0439: SQLProcessor sqlP) throws GenericEntityException {
0440: GenericDelegator delegator = entity.getDelegator();
0441:
0442: int retVal = 0;
0443: ModelEntity memberModelEntity = null;
0444:
0445: // Construct insert/update for each model entity
0446: Iterator meIter = modelViewEntity
0447: .getMemberModelMemberEntities().entrySet().iterator();
0448:
0449: while (meIter != null && meIter.hasNext()) {
0450: Map.Entry meMapEntry = (Map.Entry) meIter.next();
0451: ModelViewEntity.ModelMemberEntity modelMemberEntity = (ModelViewEntity.ModelMemberEntity) meMapEntry
0452: .getValue();
0453: String meName = modelMemberEntity.getEntityName();
0454: String meAlias = modelMemberEntity.getEntityAlias();
0455:
0456: if (Debug.verboseOn())
0457: Debug.logVerbose(
0458: "[singleUpdateView]: Processing MemberEntity "
0459: + meName + " with Alias " + meAlias,
0460: module);
0461: try {
0462: memberModelEntity = delegator.getModelReader()
0463: .getModelEntity(meName);
0464: } catch (GenericEntityException e) {
0465: throw new GenericEntityException(
0466: "Failed to get model entity for " + meName, e);
0467: }
0468:
0469: Map findByMap = new Hashtable();
0470:
0471: // Now iterate the ModelViewLinks to construct the "WHERE" part for update/insert
0472: Iterator linkIter = modelViewEntity.getViewLinksIterator();
0473:
0474: while (linkIter != null && linkIter.hasNext()) {
0475: ModelViewEntity.ModelViewLink modelViewLink = (ModelViewEntity.ModelViewLink) linkIter
0476: .next();
0477:
0478: if (modelViewLink.getEntityAlias().equals(meAlias)
0479: || modelViewLink.getRelEntityAlias().equals(
0480: meAlias)) {
0481:
0482: Iterator kmIter = modelViewLink
0483: .getKeyMapsIterator();
0484:
0485: while (kmIter != null && kmIter.hasNext()) {
0486: ModelKeyMap keyMap = (ModelKeyMap) kmIter
0487: .next();
0488:
0489: String fieldName = "";
0490:
0491: if (modelViewLink.getEntityAlias().equals(
0492: meAlias)) {
0493: fieldName = keyMap.getFieldName();
0494: } else {
0495: fieldName = keyMap.getRelFieldName();
0496: }
0497:
0498: if (Debug.verboseOn())
0499: Debug
0500: .logVerbose(
0501: "[singleUpdateView]: --- Found field to set: "
0502: + meAlias + "."
0503: + fieldName, module);
0504: Object value = null;
0505:
0506: if (modelViewEntity.isField(keyMap
0507: .getFieldName())) {
0508: value = entity.get(keyMap.getFieldName());
0509: if (Debug.verboseOn())
0510: Debug.logVerbose(
0511: "[singleUpdateView]: --- Found map value: "
0512: + value.toString(),
0513: module);
0514: } else if (modelViewEntity.isField(keyMap
0515: .getRelFieldName())) {
0516: value = entity
0517: .get(keyMap.getRelFieldName());
0518: if (Debug.verboseOn())
0519: Debug.logVerbose(
0520: "[singleUpdateView]: --- Found map value: "
0521: + value.toString(),
0522: module);
0523: } else {
0524: throw new GenericNotImplementedException(
0525: "Update on view entities: no direct link found, unable to update");
0526: }
0527:
0528: findByMap.put(fieldName, value);
0529: }
0530: }
0531: }
0532:
0533: // Look what there already is in the database
0534: List meResult = null;
0535:
0536: try {
0537: meResult = delegator.findByAnd(meName, findByMap);
0538: } catch (GenericEntityException e) {
0539: throw new GenericEntityException(
0540: "Error while retrieving partial results for entity member: "
0541: + meName, e);
0542: }
0543: if (Debug.verboseOn())
0544: Debug.logVerbose("[singleUpdateView]: --- Found "
0545: + meResult.size()
0546: + " results for entity member " + meName,
0547: module);
0548:
0549: // Got results 0 -> INSERT, 1 -> UPDATE, >1 -> View is nor updatable
0550: GenericValue meGenericValue = null;
0551:
0552: if (meResult.size() == 0) {
0553: // Create new value to insert
0554: try {
0555: // Create new value to store
0556: meGenericValue = delegator.makeValue(meName,
0557: findByMap);
0558: } catch (Exception e) {
0559: throw new GenericEntityException(
0560: "Could not create new value for member entity"
0561: + meName + " of view "
0562: + modelViewEntity.getEntityName(),
0563: e);
0564: }
0565: } else if (meResult.size() == 1) {
0566: // Update existing value
0567: meGenericValue = (GenericValue) meResult.iterator()
0568: .next();
0569: } else {
0570: throw new GenericEntityException(
0571: "Found more than one result for member entity "
0572: + meName + " in view "
0573: + modelViewEntity.getEntityName()
0574: + " - this is no updatable view");
0575: }
0576:
0577: // Construct fieldsToSave list for this member entity
0578: List meFieldsToSave = new Vector();
0579: Iterator fieldIter = fieldsToSave.iterator();
0580:
0581: while (fieldIter != null && fieldIter.hasNext()) {
0582: ModelField modelField = (ModelField) fieldIter.next();
0583:
0584: if (memberModelEntity.isField(modelField.getName())) {
0585: ModelField meModelField = memberModelEntity
0586: .getField(modelField.getName());
0587:
0588: if (meModelField != null) {
0589: meGenericValue.set(meModelField.getName(),
0590: entity.get(modelField.getName()));
0591: meFieldsToSave.add(meModelField);
0592: if (Debug.verboseOn())
0593: Debug
0594: .logVerbose(
0595: "[singleUpdateView]: --- Added field to save: "
0596: + meModelField
0597: .getName()
0598: + " with value "
0599: + meGenericValue
0600: .get(meModelField
0601: .getName()),
0602: module);
0603: } else {
0604: throw new GenericEntityException(
0605: "Could not get field "
0606: + modelField.getName()
0607: + " from model entity "
0608: + memberModelEntity
0609: .getEntityName());
0610: }
0611: }
0612: }
0613:
0614: /*
0615: * Finally, do the insert/update
0616: * TODO:
0617: * Do the real inserts/updates outside the memberEntity-loop,
0618: * only if all of the found member entities are updatable.
0619: * This avoids partial creation of member entities, which would mean data inconsistency:
0620: * If not all member entities can be updated, then none should be updated
0621: */
0622: if (meResult.size() == 0) {
0623: retVal += singleInsert(meGenericValue,
0624: memberModelEntity, memberModelEntity
0625: .getFieldsCopy(), sqlP);
0626: } else {
0627: if (meFieldsToSave.size() > 0) {
0628: retVal += singleUpdate(meGenericValue,
0629: memberModelEntity, meFieldsToSave, sqlP);
0630: } else {
0631: if (Debug.verboseOn())
0632: Debug.logVerbose(
0633: "[singleUpdateView]: No update on member entity "
0634: + memberModelEntity
0635: .getEntityName()
0636: + " needed", module);
0637: }
0638: }
0639: }
0640:
0641: return retVal;
0642: }
0643:
0644: /* ====================================================================== */
0645:
0646: /* ====================================================================== */
0647:
0648: public void select(GenericEntity entity)
0649: throws GenericEntityException {
0650: SQLProcessor sqlP = new SQLProcessor(helperName);
0651:
0652: try {
0653: select(entity, sqlP);
0654: } finally {
0655: sqlP.close();
0656: }
0657: }
0658:
0659: public void select(GenericEntity entity, SQLProcessor sqlP)
0660: throws GenericEntityException {
0661: ModelEntity modelEntity = entity.getModelEntity();
0662:
0663: if (modelEntity == null) {
0664: throw new GenericModelException(
0665: "Could not find ModelEntity record for entityName: "
0666: + entity.getEntityName());
0667: }
0668:
0669: if (modelEntity.getPksSize() <= 0) {
0670: throw new GenericEntityException(
0671: "Entity has no primary keys, cannot select by primary key");
0672: }
0673:
0674: StringBuffer sqlBuffer = new StringBuffer("SELECT ");
0675:
0676: if (modelEntity.getNopksSize() > 0) {
0677: sqlBuffer.append(modelEntity.colNameString(modelEntity
0678: .getNopksCopy(), ", ", "",
0679: datasourceInfo.aliasViews));
0680: } else {
0681: sqlBuffer.append("*");
0682: }
0683:
0684: sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity,
0685: datasourceInfo));
0686: sqlBuffer.append(SqlJdbcUtil.makeWhereClause(modelEntity,
0687: modelEntity.getPksCopy(), entity, "AND",
0688: datasourceInfo.joinStyle));
0689:
0690: try {
0691: sqlP.prepareStatement(sqlBuffer.toString(), true,
0692: ResultSet.TYPE_FORWARD_ONLY,
0693: ResultSet.CONCUR_READ_ONLY);
0694: SqlJdbcUtil.setPkValues(sqlP, modelEntity, entity,
0695: modelFieldTypeReader);
0696: sqlP.executeQuery();
0697:
0698: if (sqlP.next()) {
0699: for (int j = 0; j < modelEntity.getNopksSize(); j++) {
0700: ModelField curField = modelEntity.getNopk(j);
0701:
0702: SqlJdbcUtil.getValue(sqlP.getResultSet(), j + 1,
0703: curField, entity, modelFieldTypeReader);
0704: }
0705:
0706: entity.synchronizedWithDatasource();
0707: } else {
0708: // Debug.logWarning("[GenericDAO.select]: select failed, result set was empty for entity: " + entity.toString(), module);
0709: throw new GenericEntityNotFoundException(
0710: "Result set was empty for entity: "
0711: + entity.toString());
0712: }
0713: } finally {
0714: sqlP.close();
0715: }
0716: }
0717:
0718: public void partialSelect(GenericEntity entity, Set keys)
0719: throws GenericEntityException {
0720: ModelEntity modelEntity = entity.getModelEntity();
0721:
0722: if (modelEntity == null) {
0723: throw new GenericModelException(
0724: "Could not find ModelEntity record for entityName: "
0725: + entity.getEntityName());
0726: }
0727:
0728: if (modelEntity instanceof ModelViewEntity) {
0729: throw new org.ofbiz.entity.GenericNotImplementedException(
0730: "Operation partialSelect not supported yet for view entities");
0731: }
0732:
0733: /*
0734: if(entity == null || entity.<%=modelEntity.pkNameString(" == null || entity."," == null")%>) {
0735: Debug.logWarning("[GenericDAO.select]: Cannot select GenericEntity: required primary key field(s) missing.", module);
0736: return false;
0737: }
0738: */
0739: // we don't want to select ALL fields, just the nonpk fields that are in the passed GenericEntity
0740: List partialFields = new ArrayList();
0741:
0742: Set tempKeys = new TreeSet(keys);
0743:
0744: for (int fi = 0; fi < modelEntity.getNopksSize(); fi++) {
0745: ModelField curField = modelEntity.getNopk(fi);
0746:
0747: if (tempKeys.contains(curField.getName())) {
0748: partialFields.add(curField);
0749: tempKeys.remove(curField.getName());
0750: }
0751: }
0752:
0753: if (tempKeys.size() > 0) {
0754: throw new GenericModelException(
0755: "In partialSelect invalid field names specified: "
0756: + tempKeys.toString());
0757: }
0758:
0759: StringBuffer sqlBuffer = new StringBuffer("SELECT ");
0760:
0761: if (partialFields.size() > 0) {
0762: sqlBuffer.append(modelEntity.colNameString(partialFields,
0763: ", ", "", datasourceInfo.aliasViews));
0764: } else {
0765: sqlBuffer.append("*");
0766: }
0767: sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity,
0768: datasourceInfo));
0769: sqlBuffer.append(SqlJdbcUtil.makeWhereClause(modelEntity,
0770: modelEntity.getPksCopy(), entity, "AND",
0771: datasourceInfo.joinStyle));
0772:
0773: SQLProcessor sqlP = new SQLProcessor(helperName);
0774:
0775: try {
0776: sqlP.prepareStatement(sqlBuffer.toString(), true,
0777: ResultSet.TYPE_FORWARD_ONLY,
0778: ResultSet.CONCUR_READ_ONLY);
0779: SqlJdbcUtil.setPkValues(sqlP, modelEntity, entity,
0780: modelFieldTypeReader);
0781: sqlP.executeQuery();
0782:
0783: if (sqlP.next()) {
0784: for (int j = 0; j < partialFields.size(); j++) {
0785: ModelField curField = (ModelField) partialFields
0786: .get(j);
0787: SqlJdbcUtil.getValue(sqlP.getResultSet(), j + 1,
0788: curField, entity, modelFieldTypeReader);
0789: }
0790:
0791: entity.synchronizedWithDatasource();
0792: } else {
0793: // Debug.logWarning("[GenericDAO.select]: select failed, result set was empty.", module);
0794: throw new GenericEntityNotFoundException(
0795: "Result set was empty for entity: "
0796: + entity.toString());
0797: }
0798: } finally {
0799: sqlP.close();
0800: }
0801: }
0802:
0803: public List selectByAnd(ModelEntity modelEntity, Map fields,
0804: List orderBy) throws GenericEntityException {
0805: if (modelEntity == null) {
0806: return null;
0807: }
0808:
0809: EntityCondition entityCondition = null;
0810:
0811: if (fields != null) {
0812: entityCondition = new EntityFieldMap(fields,
0813: EntityOperator.AND);
0814: }
0815:
0816: EntityListIterator entityListIterator = null;
0817:
0818: try {
0819: entityListIterator = selectListIteratorByCondition(
0820: modelEntity, entityCondition, null, null, orderBy,
0821: null);
0822: return entityListIterator.getCompleteList();
0823: } finally {
0824: if (entityListIterator != null) {
0825: entityListIterator.close();
0826: }
0827: }
0828: }
0829:
0830: public List selectByOr(ModelEntity modelEntity, Map fields,
0831: List orderBy) throws GenericEntityException {
0832: if (modelEntity == null) {
0833: return null;
0834: }
0835:
0836: EntityCondition entityCondition = null;
0837:
0838: if (fields != null) {
0839: entityCondition = new EntityFieldMap(fields,
0840: EntityOperator.OR);
0841: }
0842:
0843: EntityListIterator entityListIterator = null;
0844:
0845: try {
0846: entityListIterator = selectListIteratorByCondition(
0847: modelEntity, entityCondition, null, null, orderBy,
0848: null);
0849: return entityListIterator.getCompleteList();
0850: } finally {
0851: if (entityListIterator != null) {
0852: entityListIterator.close();
0853: }
0854: }
0855: }
0856:
0857: /* ====================================================================== */
0858: /* ====================================================================== */
0859:
0860: /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
0861: *@param modelEntity The ModelEntity of the Entity as defined in the entity XML file
0862: *@param entityCondition The EntityCondition object that specifies how to constrain this query
0863: *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
0864: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
0865: *@return List of GenericValue objects representing the result
0866: */
0867: public List selectByCondition(ModelEntity modelEntity,
0868: EntityCondition entityCondition, Collection fieldsToSelect,
0869: List orderBy) throws GenericEntityException {
0870: EntityListIterator entityListIterator = null;
0871:
0872: try {
0873: entityListIterator = selectListIteratorByCondition(
0874: modelEntity, entityCondition, null, fieldsToSelect,
0875: orderBy, null);
0876: return entityListIterator.getCompleteList();
0877: } finally {
0878: if (entityListIterator != null) {
0879: entityListIterator.close();
0880: }
0881: }
0882: }
0883:
0884: /** Finds GenericValues by the conditions specified in the EntityCondition object, the the EntityCondition javadoc for more details.
0885: *@param modelEntity The ModelEntity of the Entity as defined in the entity XML file
0886: *@param whereEntityCondition The EntityCondition object that specifies how to constrain this query before any groupings are done (if this is a view entity with group-by aliases)
0887: *@param havingEntityCondition The EntityCondition object that specifies how to constrain this query after any groupings are done (if this is a view entity with group-by aliases)
0888: *@param fieldsToSelect The fields of the named entity to get from the database; if empty or null all fields will be retreived
0889: *@param orderBy The fields of the named entity to order the query by; optionally add a " ASC" for ascending or " DESC" for descending
0890: *@param findOptions An instance of EntityFindOptions that specifies advanced query options. See the EntityFindOptions JavaDoc for more details.
0891: *@return EntityListIterator representing the result of the query: NOTE THAT THIS MUST BE CLOSED WHEN YOU ARE
0892: * DONE WITH IT, AND DON'T LEAVE IT OPEN TOO LONG BEACUSE IT WILL MAINTAIN A DATABASE CONNECTION.
0893: */
0894: public EntityListIterator selectListIteratorByCondition(
0895: ModelEntity modelEntity,
0896: EntityCondition whereEntityCondition,
0897: EntityCondition havingEntityCondition,
0898: Collection fieldsToSelect, List orderBy,
0899: EntityFindOptions findOptions)
0900: throws GenericEntityException {
0901: if (modelEntity == null) {
0902: return null;
0903: }
0904:
0905: // if no find options passed, use default
0906: if (findOptions == null)
0907: findOptions = new EntityFindOptions();
0908:
0909: boolean verboseOn = Debug.verboseOn();
0910:
0911: if (verboseOn) {
0912: // put this inside an if statement so that we don't have to generate the string when not used...
0913: Debug.logVerbose(
0914: "Doing selectListIteratorByCondition with whereEntityCondition: "
0915: + whereEntityCondition, module);
0916: }
0917:
0918: // make two ArrayLists of fields, one for fields to select and the other for where clause fields (to find by)
0919: List selectFields = new ArrayList();
0920:
0921: if (fieldsToSelect != null && fieldsToSelect.size() > 0) {
0922: Set tempKeys = new HashSet(fieldsToSelect);
0923:
0924: for (int fi = 0; fi < modelEntity.getFieldsSize(); fi++) {
0925: ModelField curField = modelEntity.getField(fi);
0926:
0927: if (tempKeys.contains(curField.getName())) {
0928: selectFields.add(curField);
0929: tempKeys.remove(curField.getName());
0930: }
0931: }
0932:
0933: if (tempKeys.size() > 0) {
0934: throw new GenericModelException(
0935: "In selectListIteratorByCondition invalid field names specified: "
0936: + tempKeys.toString());
0937: }
0938: } else {
0939: selectFields = modelEntity.getFieldsCopy();
0940: }
0941:
0942: StringBuffer sqlBuffer = new StringBuffer("SELECT ");
0943:
0944: if (findOptions.getDistinct()) {
0945: sqlBuffer.append("DISTINCT ");
0946: }
0947:
0948: if (selectFields.size() > 0) {
0949: sqlBuffer.append(modelEntity.colNameString(selectFields,
0950: ", ", "", datasourceInfo.aliasViews));
0951: } else {
0952: sqlBuffer.append("*");
0953: }
0954:
0955: // FROM clause and when necessary the JOIN or LEFT JOIN clause(s) as well
0956: sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity,
0957: datasourceInfo));
0958:
0959: // WHERE clause
0960: StringBuffer whereString = new StringBuffer();
0961: String entityCondWhereString = "";
0962: List whereEntityConditionParams = new LinkedList();
0963:
0964: if (whereEntityCondition != null) {
0965: entityCondWhereString = whereEntityCondition
0966: .makeWhereString(modelEntity,
0967: whereEntityConditionParams);
0968: }
0969:
0970: String viewClause = SqlJdbcUtil.makeViewWhereClause(
0971: modelEntity, datasourceInfo.joinStyle);
0972:
0973: if (viewClause.length() > 0) {
0974: if (entityCondWhereString.length() > 0) {
0975: whereString.append("(");
0976: whereString.append(entityCondWhereString);
0977: whereString.append(") AND ");
0978: }
0979:
0980: whereString.append(viewClause);
0981: } else {
0982: whereString.append(entityCondWhereString);
0983: }
0984:
0985: if (whereString.length() > 0) {
0986: sqlBuffer.append(" WHERE ");
0987: sqlBuffer.append(whereString.toString());
0988: }
0989:
0990: // GROUP BY clause for view-entity
0991: if (modelEntity instanceof ModelViewEntity) {
0992: ModelViewEntity modelViewEntity = (ModelViewEntity) modelEntity;
0993: String groupByString = modelViewEntity.colNameString(
0994: modelViewEntity.getGroupBysCopy(), ", ", "", false);
0995:
0996: if (UtilValidate.isNotEmpty(groupByString)) {
0997: sqlBuffer.append(" GROUP BY ");
0998: sqlBuffer.append(groupByString);
0999: }
1000: }
1001:
1002: // HAVING clause
1003: String entityCondHavingString = "";
1004: List havingEntityConditionParams = new LinkedList();
1005:
1006: if (havingEntityCondition != null) {
1007: entityCondHavingString = havingEntityCondition
1008: .makeWhereString(modelEntity,
1009: havingEntityConditionParams);
1010: }
1011: if (entityCondHavingString.length() > 0) {
1012: sqlBuffer.append(" HAVING ");
1013: sqlBuffer.append(entityCondHavingString);
1014: }
1015:
1016: // ORDER BY clause
1017: sqlBuffer.append(SqlJdbcUtil.makeOrderByClause(modelEntity,
1018: orderBy, datasourceInfo));
1019: String sql = sqlBuffer.toString();
1020:
1021: SQLProcessor sqlP = new SQLProcessor(helperName);
1022: sqlP.prepareStatement(sql, findOptions
1023: .getSpecifyTypeAndConcur(), findOptions
1024: .getResultSetType(), findOptions
1025: .getResultSetConcurrency());
1026: if (verboseOn) {
1027: // put this inside an if statement so that we don't have to generate the string when not used...
1028: Debug.logVerbose("Setting the whereEntityConditionParams: "
1029: + whereEntityConditionParams, module);
1030: }
1031: // set all of the values from the Where EntityCondition
1032: Iterator whereEntityConditionParamsIter = whereEntityConditionParams
1033: .iterator();
1034: while (whereEntityConditionParamsIter.hasNext()) {
1035: EntityConditionParam whereEntityConditionParam = (EntityConditionParam) whereEntityConditionParamsIter
1036: .next();
1037:
1038: SqlJdbcUtil.setValue(sqlP, whereEntityConditionParam
1039: .getModelField(), modelEntity.getEntityName(),
1040: whereEntityConditionParam.getFieldValue(),
1041: modelFieldTypeReader);
1042: }
1043: if (verboseOn) {
1044: // put this inside an if statement so that we don't have to generate the string when not used...
1045: Debug.logVerbose(
1046: "Setting the havingEntityConditionParams: "
1047: + havingEntityConditionParams, module);
1048: }
1049: // set all of the values from the Having EntityCondition
1050: Iterator havingEntityConditionParamsIter = havingEntityConditionParams
1051: .iterator();
1052: while (havingEntityConditionParamsIter.hasNext()) {
1053: EntityConditionParam havingEntityConditionParam = (EntityConditionParam) havingEntityConditionParamsIter
1054: .next();
1055:
1056: SqlJdbcUtil.setValue(sqlP, havingEntityConditionParam
1057: .getModelField(), modelEntity.getEntityName(),
1058: havingEntityConditionParam.getFieldValue(),
1059: modelFieldTypeReader);
1060: }
1061:
1062: sqlP.executeQuery();
1063: return new EntityListIterator(sqlP, modelEntity, selectFields,
1064: modelFieldTypeReader);
1065: }
1066:
1067: public List selectByMultiRelation(GenericValue value,
1068: ModelRelation modelRelationOne, ModelEntity modelEntityOne,
1069: ModelRelation modelRelationTwo, ModelEntity modelEntityTwo,
1070: List orderBy) throws GenericEntityException {
1071: SQLProcessor sqlP = new SQLProcessor(helperName);
1072:
1073: // get the tables names
1074: String atable = modelEntityOne.getTableName(datasourceInfo);
1075: String ttable = modelEntityTwo.getTableName(datasourceInfo);
1076:
1077: // get the column name string to select
1078: StringBuffer selsb = new StringBuffer();
1079: ArrayList collist = new ArrayList();
1080: ArrayList fldlist = new ArrayList();
1081:
1082: for (Iterator iterator = modelEntityTwo.getFieldsIterator(); iterator
1083: .hasNext();) {
1084: ModelField mf = (ModelField) iterator.next();
1085:
1086: collist.add(mf.getColName());
1087: fldlist.add(mf.getName());
1088: selsb.append(ttable + "." + mf.getColName());
1089: if (iterator.hasNext()) {
1090: selsb.append(", ");
1091: } else {
1092: selsb.append(" ");
1093: }
1094: }
1095:
1096: // construct assoc->target relation string
1097: int kmsize = modelRelationTwo.getKeyMapsSize();
1098: StringBuffer wheresb = new StringBuffer();
1099:
1100: for (int i = 0; i < kmsize; i++) {
1101: ModelKeyMap mkm = modelRelationTwo.getKeyMap(i);
1102: String lfname = mkm.getFieldName();
1103: String rfname = mkm.getRelFieldName();
1104:
1105: if (wheresb.length() > 0) {
1106: wheresb.append(" AND ");
1107: }
1108: wheresb.append(atable + "."
1109: + modelEntityOne.getField(lfname).getColName()
1110: + " = " + ttable + "."
1111: + modelEntityTwo.getField(rfname).getColName());
1112: }
1113:
1114: // construct the source entity qualifier
1115: // get the fields from relation description
1116: kmsize = modelRelationOne.getKeyMapsSize();
1117: HashMap bindMap = new HashMap();
1118:
1119: for (int i = 0; i < kmsize; i++) {
1120: // get the equivalent column names in the relation
1121: ModelKeyMap mkm = modelRelationOne.getKeyMap(i);
1122: String sfldname = mkm.getFieldName();
1123: String lfldname = mkm.getRelFieldName();
1124: ModelField amf = modelEntityOne.getField(lfldname);
1125: String lcolname = amf.getColName();
1126: Object rvalue = value.get(sfldname);
1127:
1128: bindMap.put(amf, rvalue);
1129: // construct one condition
1130: if (wheresb.length() > 0) {
1131: wheresb.append(" AND ");
1132: }
1133: wheresb.append(atable + "." + lcolname + " = ? ");
1134: }
1135:
1136: // construct a join sql query
1137: StringBuffer sqlsb = new StringBuffer();
1138:
1139: sqlsb.append("SELECT ");
1140: sqlsb.append(selsb.toString());
1141: sqlsb.append(" FROM ");
1142: sqlsb.append(atable + ", " + ttable);
1143: sqlsb.append(" WHERE ");
1144: sqlsb.append(wheresb.toString());
1145: sqlsb.append(SqlJdbcUtil.makeOrderByClause(modelEntityTwo,
1146: orderBy, true, datasourceInfo));
1147:
1148: // now execute the query
1149: ArrayList retlist = new ArrayList();
1150: GenericDelegator gd = value.getDelegator();
1151:
1152: try {
1153: sqlP.prepareStatement(sqlsb.toString());
1154: Set entrySet = bindMap.entrySet();
1155:
1156: for (Iterator iterator = entrySet.iterator(); iterator
1157: .hasNext();) {
1158: Map.Entry entry = (Map.Entry) iterator.next();
1159: ModelField mf = (ModelField) entry.getKey();
1160: Object curvalue = entry.getValue();
1161:
1162: SqlJdbcUtil.setValue(sqlP, mf, modelEntityOne
1163: .getEntityName(), curvalue,
1164: modelFieldTypeReader);
1165: }
1166: sqlP.executeQuery();
1167: int collsize = collist.size();
1168:
1169: while (sqlP.next()) {
1170: GenericValue gv = gd.makeValue(modelEntityTwo
1171: .getEntityName(), Collections.EMPTY_MAP);
1172:
1173: // loop thru all columns for in one row
1174: for (int j = 0; j < collsize; j++) {
1175: String fldname = (String) fldlist.get(j);
1176: ModelField mf = modelEntityTwo.getField(fldname);
1177:
1178: SqlJdbcUtil.getValue(sqlP.getResultSet(), j + 1,
1179: mf, gv, modelFieldTypeReader);
1180: }
1181: retlist.add(gv);
1182: }
1183: } finally {
1184: sqlP.close();
1185: }
1186:
1187: return retlist;
1188: }
1189:
1190: public long selectCountByCondition(ModelEntity modelEntity,
1191: EntityCondition whereEntityCondition,
1192: EntityCondition havingEntityCondition)
1193: throws GenericEntityException {
1194: if (modelEntity == null) {
1195: return 0;
1196: }
1197:
1198: // if no find options passed, use default
1199: EntityFindOptions findOptions = new EntityFindOptions();
1200: boolean verboseOn = Debug.verboseOn();
1201:
1202: if (verboseOn) {
1203: // put this inside an if statement so that we don't have to generate the string when not used...
1204: Debug.logVerbose(
1205: "Doing selectListIteratorByCondition with whereEntityCondition: "
1206: + whereEntityCondition, module);
1207: }
1208:
1209: StringBuffer sqlBuffer = new StringBuffer("SELECT ");
1210:
1211: if (findOptions.getDistinct()) {
1212: sqlBuffer.append("DISTINCT ");
1213: }
1214:
1215: sqlBuffer.append("COUNT(*) ");
1216:
1217: // FROM clause and when necessary the JOIN or LEFT JOIN clause(s) as well
1218: sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity,
1219: datasourceInfo));
1220:
1221: // WHERE clause
1222: StringBuffer whereString = new StringBuffer();
1223: String entityCondWhereString = "";
1224: List whereEntityConditionParams = new LinkedList();
1225:
1226: if (whereEntityCondition != null) {
1227: entityCondWhereString = whereEntityCondition
1228: .makeWhereString(modelEntity,
1229: whereEntityConditionParams);
1230: }
1231:
1232: String viewClause = SqlJdbcUtil.makeViewWhereClause(
1233: modelEntity, datasourceInfo.joinStyle);
1234:
1235: if (viewClause.length() > 0) {
1236: if (entityCondWhereString.length() > 0) {
1237: whereString.append("(");
1238: whereString.append(entityCondWhereString);
1239: whereString.append(") AND ");
1240: }
1241:
1242: whereString.append(viewClause);
1243: } else {
1244: whereString.append(entityCondWhereString);
1245: }
1246:
1247: if (whereString.length() > 0) {
1248: sqlBuffer.append(" WHERE ");
1249: sqlBuffer.append(whereString.toString());
1250: }
1251:
1252: // GROUP BY clause for view-entity
1253: if (modelEntity instanceof ModelViewEntity) {
1254: ModelViewEntity modelViewEntity = (ModelViewEntity) modelEntity;
1255: String groupByString = modelViewEntity.colNameString(
1256: modelViewEntity.getGroupBysCopy(), ", ", "", false);
1257:
1258: if (UtilValidate.isNotEmpty(groupByString)) {
1259: sqlBuffer.append(" GROUP BY ");
1260: sqlBuffer.append(groupByString);
1261: }
1262: }
1263:
1264: // HAVING clause
1265: String entityCondHavingString = "";
1266: List havingEntityConditionParams = new LinkedList();
1267:
1268: if (havingEntityCondition != null) {
1269: entityCondHavingString = havingEntityCondition
1270: .makeWhereString(modelEntity,
1271: havingEntityConditionParams);
1272: }
1273: if (entityCondHavingString.length() > 0) {
1274: sqlBuffer.append(" HAVING ");
1275: sqlBuffer.append(entityCondHavingString);
1276: }
1277:
1278: String sql = sqlBuffer.toString();
1279:
1280: SQLProcessor sqlP = new SQLProcessor(helperName);
1281: sqlP.prepareStatement(sql, findOptions
1282: .getSpecifyTypeAndConcur(), findOptions
1283: .getResultSetType(), findOptions
1284: .getResultSetConcurrency());
1285: if (verboseOn) {
1286: // put this inside an if statement so that we don't have to generate the string when not used...
1287: Debug.logVerbose("Setting the whereEntityConditionParams: "
1288: + whereEntityConditionParams, module);
1289: }
1290: // set all of the values from the Where EntityCondition
1291: Iterator whereEntityConditionParamsIter = whereEntityConditionParams
1292: .iterator();
1293: while (whereEntityConditionParamsIter.hasNext()) {
1294: EntityConditionParam whereEntityConditionParam = (EntityConditionParam) whereEntityConditionParamsIter
1295: .next();
1296: SqlJdbcUtil.setValue(sqlP, whereEntityConditionParam
1297: .getModelField(), modelEntity.getEntityName(),
1298: whereEntityConditionParam.getFieldValue(),
1299: modelFieldTypeReader);
1300: }
1301: if (verboseOn) {
1302: // put this inside an if statement so that we don't have to generate the string when not used...
1303: Debug.logVerbose(
1304: "Setting the havingEntityConditionParams: "
1305: + havingEntityConditionParams, module);
1306: }
1307: // set all of the values from the Having EntityCondition
1308: Iterator havingEntityConditionParamsIter = havingEntityConditionParams
1309: .iterator();
1310: while (havingEntityConditionParamsIter.hasNext()) {
1311: EntityConditionParam havingEntityConditionParam = (EntityConditionParam) havingEntityConditionParamsIter
1312: .next();
1313: SqlJdbcUtil.setValue(sqlP, havingEntityConditionParam
1314: .getModelField(), modelEntity.getEntityName(),
1315: havingEntityConditionParam.getFieldValue(),
1316: modelFieldTypeReader);
1317: }
1318:
1319: try {
1320: sqlP.executeQuery();
1321: long count = 0;
1322: ResultSet resultSet = sqlP.getResultSet();
1323: if (resultSet.next()) {
1324: count = resultSet.getLong(1);
1325: }
1326: return count;
1327: } catch (SQLException e) {
1328: throw new GenericDataSourceException(
1329: "Error getting count value", e);
1330: } finally {
1331: sqlP.close();
1332: }
1333: }
1334:
1335: /* ====================================================================== */
1336:
1337: /* ====================================================================== */
1338:
1339: public int delete(GenericEntity entity)
1340: throws GenericEntityException {
1341: SQLProcessor sqlP = new SQLProcessor(helperName);
1342:
1343: try {
1344: return delete(entity, sqlP);
1345: } catch (GenericDataSourceException e) {
1346: sqlP.rollback();
1347: throw new GenericDataSourceException(
1348: "Exception while deleting the following entity: "
1349: + entity.toString(), e);
1350: } finally {
1351: sqlP.close();
1352: }
1353: }
1354:
1355: public int delete(GenericEntity entity, SQLProcessor sqlP)
1356: throws GenericEntityException {
1357: ModelEntity modelEntity = entity.getModelEntity();
1358: if (modelEntity == null) {
1359: throw new GenericModelException(
1360: "Could not find ModelEntity record for entityName: "
1361: + entity.getEntityName());
1362: }
1363: if (modelEntity instanceof ModelViewEntity) {
1364: throw new org.ofbiz.entity.GenericNotImplementedException(
1365: "Operation delete not supported yet for view entities");
1366: }
1367:
1368: String sql = "DELETE FROM "
1369: + modelEntity.getTableName(datasourceInfo)
1370: + " WHERE "
1371: + SqlJdbcUtil.makeWhereStringFromFields(modelEntity
1372: .getPksCopy(), entity, "AND");
1373:
1374: int retVal;
1375:
1376: try {
1377: sqlP.prepareStatement(sql);
1378: SqlJdbcUtil.setPkValues(sqlP, modelEntity, entity,
1379: modelFieldTypeReader);
1380: retVal = sqlP.executeUpdate();
1381: entity.removedFromDatasource();
1382: } finally {
1383: sqlP.close();
1384: }
1385: return retVal;
1386: }
1387:
1388: public int deleteByAnd(ModelEntity modelEntity, Map fields)
1389: throws GenericEntityException {
1390: SQLProcessor sqlP = new SQLProcessor(helperName);
1391:
1392: try {
1393: return deleteByAnd(modelEntity, fields, sqlP);
1394: } catch (GenericDataSourceException e) {
1395: sqlP.rollback();
1396: throw new GenericDataSourceException(
1397: "Generic Entity Exception occurred in deleteByAnd",
1398: e);
1399: } finally {
1400: sqlP.close();
1401: }
1402: }
1403:
1404: public int deleteByAnd(ModelEntity modelEntity, Map fields,
1405: SQLProcessor sqlP) throws GenericEntityException {
1406: if (modelEntity == null || fields == null)
1407: return 0;
1408: if (modelEntity instanceof ModelViewEntity) {
1409: throw new org.ofbiz.entity.GenericNotImplementedException(
1410: "Operation deleteByAnd not supported yet for view entities");
1411: }
1412:
1413: List whereFields = new ArrayList();
1414: if (fields != null && fields.size() > 0) {
1415: for (int fi = 0; fi < modelEntity.getFieldsSize(); fi++) {
1416: ModelField curField = modelEntity.getField(fi);
1417:
1418: if (fields.containsKey(curField.getName())) {
1419: whereFields.add(curField);
1420: }
1421: }
1422: }
1423:
1424: GenericValue dummyValue = new GenericValue(modelEntity, fields);
1425: String sql = "DELETE FROM "
1426: + modelEntity.getTableName(datasourceInfo);
1427: if (fields != null && fields.size() > 0) {
1428: sql += " WHERE "
1429: + SqlJdbcUtil.makeWhereStringFromFields(
1430: whereFields, dummyValue, "AND");
1431: }
1432:
1433: try {
1434: sqlP.prepareStatement(sql);
1435:
1436: if (fields != null && fields.size() > 0) {
1437: SqlJdbcUtil.setValuesWhereClause(sqlP, whereFields,
1438: dummyValue, modelFieldTypeReader);
1439: }
1440:
1441: return sqlP.executeUpdate();
1442: } finally {
1443: sqlP.close();
1444: }
1445: }
1446:
1447: /** Called dummyPKs because they can be invalid PKs, doing a deleteByAnd instead of a normal delete */
1448: public int deleteAll(List dummyPKs) throws GenericEntityException {
1449: if (dummyPKs == null || dummyPKs.size() == 0) {
1450: return 0;
1451: }
1452:
1453: SQLProcessor sqlP = new SQLProcessor(helperName);
1454: try {
1455: Iterator iter = dummyPKs.iterator();
1456:
1457: int numDeleted = 0;
1458:
1459: while (iter.hasNext()) {
1460: GenericEntity entity = (GenericEntity) iter.next();
1461:
1462: // if it contains a complete primary key, delete the one, otherwise deleteByAnd
1463: if (entity.containsPrimaryKey()) {
1464: numDeleted += delete(entity, sqlP);
1465: } else {
1466: numDeleted += deleteByAnd(entity.getModelEntity(),
1467: entity.getAllFields(), sqlP);
1468: }
1469: }
1470: return numDeleted;
1471: } catch (GenericDataSourceException e) {
1472: sqlP.rollback();
1473: throw new GenericDataSourceException(
1474: "Generic Entity Exception occurred in deleteAll", e);
1475: } finally {
1476: sqlP.close();
1477: }
1478: }
1479:
1480: /* ====================================================================== */
1481:
1482: public void checkDb(Map modelEntities, List messages,
1483: boolean addMissing) {
1484: DatabaseUtil dbUtil = new DatabaseUtil(this .helperName);
1485: dbUtil.checkDb(modelEntities, messages, addMissing);
1486: }
1487:
1488: /** Creates a list of ModelEntity objects based on meta data from the database */
1489: public List induceModelFromDb(Collection messages) {
1490: DatabaseUtil dbUtil = new DatabaseUtil(this.helperName);
1491: return dbUtil.induceModelFromDb(messages);
1492: }
1493: }
|