use of org.apache.ofbiz.entity.model.ModelField in project ofbiz-framework by apache.
the class GenericDAO method selectCountByCondition.
public long selectCountByCondition(Delegator delegator, ModelEntity modelEntity, EntityCondition whereEntityCondition, EntityCondition havingEntityCondition, List<ModelField> selectFields, EntityFindOptions findOptions) throws GenericEntityException {
if (modelEntity == null) {
return 0;
}
// if no find options passed, use default
if (findOptions == null) {
findOptions = new EntityFindOptions();
}
boolean verboseOn = Debug.verboseOn();
if (verboseOn) {
// put this inside an if statement so that we don't have to generate the string when not used...
if (Debug.verboseOn())
Debug.logVerbose("Doing selectListIteratorByCondition with whereEntityCondition: " + whereEntityCondition, module);
}
boolean isGroupBy = false;
ModelViewEntity modelViewEntity = null;
if (modelEntity instanceof ModelViewEntity) {
modelViewEntity = (ModelViewEntity) modelEntity;
isGroupBy = modelViewEntity.getGroupBysSize() > 0;
}
// To get a count of the rows that will be returned when there is a GROUP BY, must do something like:
// SELECT COUNT(1) FROM (SELECT COUNT(1) FROM OFBIZ.POSTAL_ADDRESS PA GROUP BY PA.CITY) TEMP_NAME
// instead of a simple:
// SELECT COUNT(1) FROM OFBIZ.POSTAL_ADDRESS PA GROUP BY PA.CITY
StringBuilder sqlBuffer = new StringBuilder("SELECT ");
if (isGroupBy) {
sqlBuffer.append("COUNT(1) FROM (SELECT ");
}
if (findOptions.getDistinct()) {
/* DEJ20100304: the code below was causing problems so the line above may be used instead, but hopefully this is fixed now
* may need varying SQL for different databases, and also in view-entities in some cases it seems to
* cause the "COUNT(DISTINCT " to appear twice, causing an attempt to try to count a count (function="count-distinct", distinct=true in find options)
*/
if (selectFields != null && selectFields.size() > 0) {
ModelField firstSelectField = selectFields.get(0);
ModelViewEntity.ModelAlias firstModelAlias = modelViewEntity != null ? modelViewEntity.getAlias(firstSelectField.getName()) : null;
if (firstModelAlias != null && UtilValidate.isNotEmpty(firstModelAlias.getFunction())) {
// if the field has a function already we don't want to count just it, would be meaningless
sqlBuffer.append("COUNT(DISTINCT *) ");
} else {
sqlBuffer.append("COUNT(DISTINCT ");
// this only seems to support a single column, which is not desirable but seems a lot better than no columns or in certain cases all columns
sqlBuffer.append(firstSelectField.getColValue());
// sqlBuffer.append(modelEntity.colNameString(selectFields, ", ", "", datasource.aliasViews));
sqlBuffer.append(")");
}
} else {
sqlBuffer.append("COUNT(DISTINCT *) ");
}
} else {
// NOTE DEJ20080701 Changed from COUNT(*) to COUNT(1) to improve performance, and should get the same results at least when there is no DISTINCT
sqlBuffer.append("COUNT(1) ");
}
// populate the info from entity-condition in the view-entity, if it is one and there is one
List<EntityCondition> viewWhereConditions = null;
List<EntityCondition> viewHavingConditions = null;
List<String> viewOrderByList = null;
if (modelViewEntity != null) {
viewWhereConditions = new LinkedList<EntityCondition>();
viewHavingConditions = new LinkedList<EntityCondition>();
viewOrderByList = new LinkedList<String>();
modelViewEntity.populateViewEntityConditionInformation(modelFieldTypeReader, viewWhereConditions, viewHavingConditions, viewOrderByList, null);
}
// FROM clause and when necessary the JOIN or LEFT JOIN clause(s) as well
sqlBuffer.append(SqlJdbcUtil.makeFromClause(modelEntity, modelFieldTypeReader, datasource));
// WHERE clause
List<EntityConditionParam> whereEntityConditionParams = new LinkedList<EntityConditionParam>();
makeConditionWhereString(sqlBuffer, " WHERE ", modelEntity, whereEntityCondition, viewWhereConditions, whereEntityConditionParams);
// GROUP BY clause for view-entity
if (isGroupBy) {
modelViewEntity.colNameString(modelViewEntity.getGroupBysCopy(), sqlBuffer, " GROUP BY ", ", ", "", false);
}
// HAVING clause
List<EntityConditionParam> havingEntityConditionParams = new LinkedList<EntityConditionParam>();
makeConditionHavingString(sqlBuffer, " HAVING ", modelEntity, havingEntityCondition, viewHavingConditions, havingEntityConditionParams);
if (isGroupBy) {
sqlBuffer.append(") TEMP_NAME");
}
String sql = sqlBuffer.toString();
if (Debug.verboseOn())
Debug.logVerbose("Count select sql: " + sql, module);
try (SQLProcessor sqlP = new SQLProcessor(delegator, helperInfo)) {
sqlP.prepareStatement(sql, findOptions.getSpecifyTypeAndConcur(), findOptions.getResultSetType(), findOptions.getResultSetConcurrency(), findOptions.getFetchSize(), findOptions.getMaxRows());
if (verboseOn) {
// put this inside an if statement so that we don't have to generate the string when not used...
if (Debug.verboseOn())
Debug.logVerbose("Setting the whereEntityConditionParams: " + whereEntityConditionParams, module);
}
// set all of the values from the Where EntityCondition
for (EntityConditionParam whereEntityConditionParam : whereEntityConditionParams) {
SqlJdbcUtil.setValue(sqlP, whereEntityConditionParam.getModelField(), modelEntity.getEntityName(), whereEntityConditionParam.getFieldValue(), modelFieldTypeReader);
}
if (verboseOn) {
// put this inside an if statement so that we don't have to generate the string when not used...
if (Debug.verboseOn())
Debug.logVerbose("Setting the havingEntityConditionParams: " + havingEntityConditionParams, module);
}
// set all of the values from the Having EntityCondition
for (EntityConditionParam havingEntityConditionParam : havingEntityConditionParams) {
SqlJdbcUtil.setValue(sqlP, havingEntityConditionParam.getModelField(), modelEntity.getEntityName(), havingEntityConditionParam.getFieldValue(), modelFieldTypeReader);
}
try {
sqlP.executeQuery();
long count = 0;
ResultSet resultSet = sqlP.getResultSet();
if (resultSet.next()) {
count = resultSet.getLong(1);
}
return count;
} catch (SQLException e) {
throw new GenericDataSourceException("Error getting count value", e);
}
}
}
use of org.apache.ofbiz.entity.model.ModelField in project ofbiz-framework by apache.
the class GenericDAO method singleUpdateView.
/* ====================================================================== */
/* ====================================================================== */
/**
* Try to update the given ModelViewEntity by trying to insert/update on the entities of which the view is composed.
*
* Works fine with standard O/R mapped models, but has some restrictions meeting more complicated view entities.
* <li>A direct link is required, which means that one of the ModelViewLink field entries must have a value found
* in the given view entity, for each ModelViewLink</li>
* <li>For now, each member entity is updated iteratively, so if eg. the second member entity fails to update,
* the first is written although. See code for details. Try to use "clean" views, until code is more robust ...</li>
* <li>For now, aliased field names in views are not processed correctly, I guess. To be honest, I did not
* find out how to construct such a view - so view fieldnames must have same named fields in member entities.</li>
* <li>A new exception, e.g. GenericViewNotUpdatable, should be defined and thrown if the update fails</li>
*/
private int singleUpdateView(GenericEntity entity, ModelViewEntity modelViewEntity, List<ModelField> fieldsToSave, SQLProcessor sqlP) throws GenericEntityException {
Delegator delegator = entity.getDelegator();
int retVal = 0;
ModelEntity memberModelEntity = null;
// Construct insert/update for each model entity
for (ModelViewEntity.ModelMemberEntity modelMemberEntity : modelViewEntity.getMemberModelMemberEntities().values()) {
String meName = modelMemberEntity.getEntityName();
String meAlias = modelMemberEntity.getEntityAlias();
if (Debug.verboseOn())
Debug.logVerbose("[singleUpdateView]: Processing MemberEntity " + meName + " with Alias " + meAlias, module);
try {
memberModelEntity = delegator.getModelReader().getModelEntity(meName);
} catch (GenericEntityException e) {
throw new GenericEntityException("Failed to get model entity for " + meName, e);
}
Map<String, Object> findByMap = new HashMap<String, Object>();
// Now iterate the ModelViewLinks to construct the "WHERE" part for update/insert
Iterator<ModelViewEntity.ModelViewLink> linkIter = modelViewEntity.getViewLinksIterator();
while (linkIter != null && linkIter.hasNext()) {
ModelViewEntity.ModelViewLink modelViewLink = linkIter.next();
if (modelViewLink.getEntityAlias().equals(meAlias) || modelViewLink.getRelEntityAlias().equals(meAlias)) {
Iterator<ModelKeyMap> kmIter = modelViewLink.getKeyMapsIterator();
while (kmIter != null && kmIter.hasNext()) {
ModelKeyMap keyMap = kmIter.next();
String fieldName = "";
if (modelViewLink.getEntityAlias().equals(meAlias)) {
fieldName = keyMap.getFieldName();
} else {
fieldName = keyMap.getRelFieldName();
}
if (Debug.verboseOn())
Debug.logVerbose("[singleUpdateView]: --- Found field to set: " + meAlias + "." + fieldName, module);
Object value = null;
if (modelViewEntity.isField(keyMap.getFieldName())) {
value = entity.get(keyMap.getFieldName());
if (Debug.verboseOn())
Debug.logVerbose("[singleUpdateView]: --- Found map value: " + value.toString(), module);
} else if (modelViewEntity.isField(keyMap.getRelFieldName())) {
value = entity.get(keyMap.getRelFieldName());
if (Debug.verboseOn())
Debug.logVerbose("[singleUpdateView]: --- Found map value: " + value.toString(), module);
} else {
throw new GenericNotImplementedException("Update on view entities: no direct link found, unable to update");
}
findByMap.put(fieldName, value);
}
}
}
// Look what there already is in the database
List<GenericValue> meResult = null;
try {
meResult = EntityQuery.use(delegator).from(meName).where(findByMap).queryList();
} catch (GenericEntityException e) {
throw new GenericEntityException("Error while retrieving partial results for entity member: " + meName, e);
}
if (Debug.verboseOn())
Debug.logVerbose("[singleUpdateView]: --- Found " + meResult.size() + " results for entity member " + meName, module);
// Got results 0 -> INSERT, 1 -> UPDATE, >1 -> View is nor updatable
GenericValue meGenericValue = null;
if (meResult.size() == 0) {
// Create new value to insert
try {
// Create new value to store
meGenericValue = delegator.makeValue(meName, findByMap);
} catch (Exception e) {
throw new GenericEntityException("Could not create new value for member entity" + meName + " of view " + modelViewEntity.getEntityName(), e);
}
} else if (meResult.size() == 1) {
// Update existing value
meGenericValue = meResult.iterator().next();
} else {
throw new GenericEntityException("Found more than one result for member entity " + meName + " in view " + modelViewEntity.getEntityName() + " - this is no updatable view");
}
// Construct fieldsToSave list for this member entity
List<ModelField> meFieldsToSave = new LinkedList<ModelField>();
for (ModelField modelField : fieldsToSave) {
if (memberModelEntity.isField(modelField.getName())) {
ModelField meModelField = memberModelEntity.getField(modelField.getName());
if (meModelField != null) {
meGenericValue.set(meModelField.getName(), entity.get(modelField.getName()));
meFieldsToSave.add(meModelField);
if (Debug.verboseOn())
Debug.logVerbose("[singleUpdateView]: --- Added field to save: " + meModelField.getName() + " with value " + meGenericValue.get(meModelField.getName()), module);
} else {
throw new GenericEntityException("Could not get field " + modelField.getName() + " from model entity " + memberModelEntity.getEntityName());
}
}
}
/*
* Finally, do the insert/update
* TODO:
* Do the real inserts/updates outside the memberEntity-loop,
* only if all of the found member entities are updatable.
* This avoids partial creation of member entities, which would mean data inconsistency:
* If not all member entities can be updated, then none should be updated
*/
if (meResult.size() == 0) {
retVal += singleInsert(meGenericValue, memberModelEntity, memberModelEntity.getFieldsUnmodifiable(), sqlP);
} else {
if (meFieldsToSave.size() > 0) {
retVal += singleUpdate(meGenericValue, memberModelEntity, meFieldsToSave, sqlP);
} else {
if (Debug.verboseOn())
Debug.logVerbose("[singleUpdateView]: No update on member entity " + memberModelEntity.getEntityName() + " needed", module);
}
}
}
return retVal;
}
use of org.apache.ofbiz.entity.model.ModelField in project ofbiz-framework by apache.
the class GenericEntity method set.
/**
* Sets the named field to the passed value. If value is null, it is only
* set if the setIfNull parameter is true. This is useful because an update
* will only set values that are included in the HashMap and will store null
* values in the HashMap to the datastore. If a value is not in the HashMap,
* it will be left unmodified in the datastore.
* @param name The field name to set
* @param value The value to set
* @param setIfNull Specifies whether or not to set the value if it is null
*/
public Object set(String name, Object value, boolean setIfNull) {
assertIsMutable();
ModelField modelField = getModelEntity().getField(name);
if (modelField == null) {
throw new IllegalArgumentException("[GenericEntity.set] \"" + name + "\" is not a field of " + entityName + ", must be one of: " + getModelEntity().fieldNameString());
}
if (value != null || setIfNull) {
ModelFieldType type = null;
try {
type = getDelegator().getEntityFieldType(getModelEntity(), modelField.getType());
} catch (IllegalStateException | GenericEntityException e) {
Debug.logWarning(e, module);
}
if (type == null) {
throw new IllegalArgumentException("Type " + modelField.getType() + " not found for entity [" + this.getEntityName() + "]; probably because there is no datasource (helper) setup for the entity group that this entity is in: [" + this.getDelegator().getEntityGroupName(this.getEntityName()) + "]");
}
if (value instanceof Boolean) {
// if this is a Boolean check to see if we should convert from an indicator or just leave as is
try {
int fieldType = SqlJdbcUtil.getType(type.getJavaType());
if (fieldType != 10) {
value = ((Boolean) value).booleanValue() ? "Y" : "N";
}
} catch (GenericNotImplementedException e) {
throw new IllegalArgumentException(e.getMessage());
}
} else if (value != null && !(value instanceof NULL)) {
// make sure the type matches the field Java type
if (value instanceof TimeDuration) {
try {
value = ObjectType.simpleTypeConvert(value, type.getJavaType(), null, null);
} catch (GeneralException e) {
Debug.logError(e, module);
}
} else if ((value instanceof String) && "byte[]".equals(type.getJavaType())) {
value = ((String) value).getBytes(UtilIO.getUtf8());
}
if (!ObjectType.instanceOf(value, type.getJavaType())) {
if (!("java.sql.Blob".equals(type.getJavaType()) && (value instanceof byte[] || ObjectType.instanceOf(value, ByteBuffer.class)))) {
String errMsg = "In entity field [" + this.getEntityName() + "." + name + "] set the value passed in [" + value.getClass().getName() + "] is not compatible with the Java type of the field [" + type.getJavaType() + "]";
// eventually we should do this, but for now we'll do a "soft" failure: throw new IllegalArgumentException(errMsg);
Debug.logWarning(new Exception("Location of database type warning"), "=-=-=-=-=-=-=-=-= Database type warning GenericEntity.set =-=-=-=-=-=-=-=-= " + errMsg, module);
}
}
}
Object old = fields.put(name, value);
generateHashCode = true;
this.setChanged();
this.notifyObservers(name);
return old;
}
return fields.get(name);
}
use of org.apache.ofbiz.entity.model.ModelField in project ofbiz-framework by apache.
the class GenericEntity method makeXmlElement.
/**
* Makes an XML Element object with an attribute for each field of the entity
*@param document The XML Document that the new Element will be part of
*@param prefix A prefix to put in front of the entity name in the tag name
*@return org.w3c.dom.Element object representing this generic entity
*/
public Element makeXmlElement(Document document, String prefix) {
Element element = null;
if (prefix == null) {
prefix = "";
}
if (document != null) {
element = document.createElement(prefix + this.getEntityName());
}
if (element == null) {
return null;
}
Iterator<ModelField> modelFields = this.getModelEntity().getFieldsIterator();
while (modelFields.hasNext()) {
ModelField modelField = modelFields.next();
String name = modelField.getName();
String value = this.getString(name);
if (value != null) {
if (value.indexOf('\n') >= 0 || value.indexOf('\r') >= 0) {
UtilXml.addChildElementCDATAValue(element, name, value, document);
} else {
element.setAttribute(name, value);
}
}
}
return element;
}
use of org.apache.ofbiz.entity.model.ModelField in project ofbiz-framework by apache.
the class GenericEntity method compareTo.
/**
* Compares this GenericEntity to the passed object
*@param that Object to compare this to
*@return int representing the result of the comparison (-1,0, or 1)
*/
public int compareTo(GenericEntity that) {
// if null, it will push to the beginning
if (that == null) {
return -1;
}
int tempResult = this.entityName.compareTo(that.entityName);
// if they did not match, we know the order, otherwise compare the primary keys
if (tempResult != 0) {
return tempResult;
}
// both have same entityName, should be the same so let's compare PKs
Iterator<ModelField> pkIter = getModelEntity().getPksIterator();
while (pkIter.hasNext()) {
ModelField curField = pkIter.next();
tempResult = compareToFields(that, curField.getName());
if (tempResult != 0) {
return tempResult;
}
}
// okay, if we got here it means the primaryKeys are exactly the SAME, so compare the rest of the fields
Iterator<ModelField> nopkIter = getModelEntity().getNopksIterator();
while (nopkIter.hasNext()) {
ModelField curField = nopkIter.next();
if (!curField.getIsAutoCreatedInternal()) {
tempResult = compareToFields(that, curField.getName());
if (tempResult != 0) {
return tempResult;
}
}
}
// if we got here it means the two are exactly the same, so return tempResult, which should be 0
return tempResult;
}
Aggregations