/*******************************************************************************
* * Copyright 2012 Impetus Infotech.
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * http://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
******************************************************************************/
package com.impetus.kundera.query;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Parameter;
import javax.persistence.PersistenceException;
import javax.persistence.PostLoad;
import javax.persistence.Query;
import javax.persistence.TemporalType;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EntityType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.impetus.kundera.Constants;
import com.impetus.kundera.client.Client;
import com.impetus.kundera.client.EnhanceEntity;
import com.impetus.kundera.metadata.model.ApplicationMetadata;
import com.impetus.kundera.metadata.model.EntityMetadata;
import com.impetus.kundera.metadata.model.MetamodelImpl;
import com.impetus.kundera.metadata.model.attributes.AbstractAttribute;
import com.impetus.kundera.metadata.model.type.DefaultEntityType;
import com.impetus.kundera.persistence.EntityManagerFactoryImpl.KunderaMetadata;
import com.impetus.kundera.persistence.EntityReader;
import com.impetus.kundera.persistence.PersistenceDelegator;
import com.impetus.kundera.persistence.context.PersistenceCacheManager;
import com.impetus.kundera.property.PropertyAccessorHelper;
import com.impetus.kundera.query.KunderaQuery.FilterClause;
import com.impetus.kundera.query.KunderaQuery.UpdateClause;
import com.impetus.kundera.utils.KunderaCoreUtils;
import com.impetus.kundera.utils.ReflectUtils;
/**
* The Class QueryImpl.
*
* @author vivek.mishra
* @param <E>
*/
public abstract class QueryImpl<E> implements Query, com.impetus.kundera.query.Query
{
/** The kundera query. */
protected KunderaQuery kunderaQuery;
/** The persistence delegeator. */
protected PersistenceDelegator persistenceDelegeator;
protected KunderaMetadata kunderaMetadata;
/** The log. */
private static Logger log = LoggerFactory.getLogger(QueryImpl.class);
private Set<Parameter<?>> parameters;
private Map<String, Object> hints = new HashMap<String, Object>();
/**
* Default maximum result to fetch.
*/
protected int maxResult = 100;
protected int firstResult = 0;
private Integer fetchSize;
protected boolean isSingleResult = false;
protected Integer ttl;
/**
* Instantiates a new query impl.
*
* @param query
* the query
* @param persistenceDelegator
* the persistence delegator
* @param persistenceUnits
* the persistence units
*/
public QueryImpl(KunderaQuery kunderaQuery, PersistenceDelegator persistenceDelegator,
final KunderaMetadata kunderaMetadata)
{
this.kunderaQuery = kunderaQuery;
this.persistenceDelegeator = persistenceDelegator;
this.kunderaMetadata = kunderaMetadata;
}
/**
* Gets the jPA query.
*
* @return the jPA query
*/
public String getJPAQuery()
{
return kunderaQuery.getJPAQuery();
}
/**
* Gets the kundera query.
*
* @return the kunderaQuery
*/
public KunderaQuery getKunderaQuery()
{
return kunderaQuery;
}
@Override
public int executeUpdate()
{
return onExecuteUpdate();
}
@Override
public List<?> getResultList()
{
if (log.isDebugEnabled())
log.info("On getResultList() executing query: " + getJPAQuery());
// as per JPA post event should happen before fetching data from
// database.
handlePostEvent();
List results = null;
if (kunderaQuery.isDeleteUpdate())
{
executeUpdate();
}
else
{
results = fetch();
assignReferenceToProxy(results);
}
return results != null ? results : new ArrayList();
}
protected List<Object> setRelationEntities(List enhanceEntities, Client client, EntityMetadata m)
{
// Enhance entities can contain or may not contain relation.
// if it contain a relation means it is a child
// if it does not then it means it is a parent.
List<Object> result = new ArrayList<Object>();
if (enhanceEntities != null)
{
for (Object e : enhanceEntities)
{
if (!(e instanceof EnhanceEntity))
{
e = new EnhanceEntity(e, PropertyAccessorHelper.getId(e, m), null);
}
EnhanceEntity ee = (EnhanceEntity) e;
result.add(getReader().recursivelyFindEntities(ee.getEntity(), ee.getRelations(), m,
persistenceDelegeator, false));
}
}
return result;
}
/**
* Populate using lucene for embeddeId
*
* @param m
* @param client
* @param result
* @param searchFilter
* @param columnsToSelect
* @return
*/
private List<Object> populateEmbeddedIdUsingLucene(EntityMetadata m, Client client, List<Object> result,
Map<String, Object> searchFilter, String[] columnsToSelect)
{
List<Object> compositeIds = new ArrayList<Object>();
for (String compositeIdName : searchFilter.keySet())
{
Object compositeId = null;
Map<String, String> uniquePKs = (Map<String, String>) searchFilter.get(compositeIdName);
compositeId = KunderaCoreUtils.initialize(m.getIdAttribute().getBindableJavaType(), compositeId);
for (Field field : m.getIdAttribute().getBindableJavaType().getDeclaredFields())
{
if (!ReflectUtils.isTransientOrStatic(field))
{
PropertyAccessorHelper.set(
compositeId,
field,
PropertyAccessorHelper.fromSourceToTargetClass(field.getType(), String.class,
uniquePKs.get(field.getName())));
}
}
compositeIds.add(compositeId);
}
return findUsingLucene(m, client, compositeIds.toArray());
}
/**
* find data using lucene
* @param m
* @param client
* @param primaryKeys
* @return
*/
private List<Object> findUsingLucene(EntityMetadata m, Client client, Object[] primaryKeys)
{
String idField = m.getIdAttribute().getName();
String equals = "=";
MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
m.getPersistenceUnit());
EntityType entityType = metaModel.entity(m.getEntityClazz());
String columnName = ((AbstractAttribute) entityType.getAttribute(idField)).getJPAColumnName();
List<Object> result = new ArrayList<Object>();
Queue queue = getKunderaQuery().getFilterClauseQueue();
KunderaQuery kunderaQuery = getKunderaQuery();
for (Object primaryKey : primaryKeys)
{
FilterClause filterClause = kunderaQuery.new FilterClause(columnName, equals, primaryKey);
kunderaQuery.setFilter(kunderaQuery.getEntityAlias()+"."+columnName +" = "+primaryKey);
queue.clear();
queue.add(filterClause);
List<Object> object = findUsingLucene(m, client);
if (object != null && !object.isEmpty())
result.add(object.get(0));
}
return result;
}
/**
* Populate using lucene.
*
* @param m
* the m
* @param client
* the client
* @param result
* the result
* @param columnsToSelect
* List of column names to be selected (rest should be ignored)
* @return the list
*/
protected List<Object> populateUsingLucene(EntityMetadata m, Client client, List<Object> result,
String[] columnsToSelect)
{
MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
m.getPersistenceUnit());
String luceneQ = KunderaCoreUtils.getLuceneQueryFromJPAQuery(kunderaQuery, kunderaMetadata);
Map<String, Object> searchFilter = client.getIndexManager().search(m.getEntityClazz(), luceneQ,
Constants.INVALID, Constants.INVALID);
boolean isEmbeddedId = metaModel.isEmbeddable(m.getIdAttribute().getBindableJavaType());
if (isEmbeddedId)
{
return populateEmbeddedIdUsingLucene(m, client, result, searchFilter, columnsToSelect);
}
String[] primaryKeys = searchFilter.values().toArray(new String[] {});
Set<String> uniquePKs = new HashSet<String>(Arrays.asList(primaryKeys));
return findUsingLucene(m, client, uniquePKs.toArray());
}
/**
* Populate entities, Method to populate data in case no relation exist!.
*
* @param m
* the m
* @param client
* the client
* @return the list
*/
protected abstract List<Object> populateEntities(EntityMetadata m, Client client);
protected abstract List findUsingLucene(EntityMetadata m, Client client);
/**
* Recursively populate entities.
*
*
* @param m
* @param client
* @return
*/
protected abstract List<Object> recursivelyPopulateEntities(EntityMetadata m, Client client);
/**
* Method returns entity reader.
*
* @return entityReader entity reader.
*/
protected abstract EntityReader getReader();
/**
* Method to be invoked on query.executeUpdate().
*
* @return
*/
protected abstract int onExecuteUpdate();
/**
* Returns entity metadata, in case of native query mapped class is present
* within application metadata.
*
* @return entityMetadata entity metadata.
*/
protected EntityMetadata getEntityMetadata()
{
return kunderaQuery.getEntityMetadata();
}
protected int onUpdateDeleteEvent()
{
if (kunderaQuery.isDeleteUpdate())
{
List result = fetch();
onDeleteOrUpdate(result);
return result != null ? result.size() : 0;
}
return 0;
}
/**
* Performs delete or update based on query.
*
* @param results
* list of objects to be merged/deleted.
*/
protected void onDeleteOrUpdate(List results)
{
if (results != null)
{
if (!kunderaQuery.isUpdateClause())
{
// then case of delete
for (Object result : results)
{
PersistenceCacheManager.addEntityToPersistenceCache(result, persistenceDelegeator,
PropertyAccessorHelper.getId(result, this.getEntityMetadata()));
persistenceDelegeator.remove(result);
}
}
else
{
EntityMetadata entityMetadata = getEntityMetadata();
for (Object result : results)
{
PersistenceCacheManager.addEntityToPersistenceCache(result, persistenceDelegeator,
PropertyAccessorHelper.getId(result, this.getEntityMetadata()));
for (UpdateClause c : kunderaQuery.getUpdateClauseQueue())
{
String columnName = c.getProperty();
try
{
DefaultEntityType entityType = (DefaultEntityType) kunderaMetadata.getApplicationMetadata()
.getMetamodel(entityMetadata.getPersistenceUnit())
.entity(entityMetadata.getEntityClazz());
// That will always be attribute name.
Attribute attribute = entityType.getAttribute(columnName);
// TODO : catch column name.
if (c.getValue() instanceof String)
{
PropertyAccessorHelper.set(result, (Field) attribute.getJavaMember(), c.getValue()
.toString());
}
else
{
PropertyAccessorHelper.set(result, (Field) attribute.getJavaMember(), c.getValue());
}
persistenceDelegeator.merge(result);
}
catch (IllegalArgumentException iax)
{
log.error("Invalid column name: " + columnName + " for class : "
+ entityMetadata.getEntityClazz());
throw new QueryHandlerException("Error while executing query: " + iax);
}
}
}
}
}
}
/************************* Methods from {@link Query} interface *******************************/
/* @see javax.persistence.Query#getSingleResult() */
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#getSingleResult()
*/
@Override
public Object getSingleResult()
{
// to fetch a single result form database.
isSingleResult = true;
List results = getResultList();
isSingleResult = false;
return onReturnResults(results);
}
/* @see javax.persistence.Query#setFirstResult(int) */
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#setFirstResult(int)
*/
@Override
public Query setFirstResult(int startPosition)
{
this.firstResult = startPosition;
return this;
}
/*
* @see
* javax.persistence.Query#setFlushMode(javax.persistence.FlushModeType)
*/
/*
* (non-Javadoc)
*
* @see
* javax.persistence.Query#setFlushMode(javax.persistence.FlushModeType)
*/
@Override
public Query setFlushMode(FlushModeType flushMode)
{
throw new UnsupportedOperationException("setFlushMode is unsupported by Kundera");
}
/**
* Sets hint name and value into hints map and returns instance of
* {@link Query}
*/
@Override
public Query setHint(String hintName, Object value)
{
hints.put(hintName, value);
return this;
}
/* @see javax.persistence.Query#setMaxResults(int) */
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#setMaxResults(int)
*/
@Override
public Query setMaxResults(int maxResult)
{
this.maxResult = maxResult;
return this;
}
/*
* @see javax.persistence.Query#setParameter(java.lang.String,
* java.lang.Object)
*/
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#setParameter(java.lang.String,
* java.lang.Object)
*/
@Override
public Query setParameter(String name, Object value)
{
kunderaQuery.setParameter(name, value);
return this;
}
/* @see javax.persistence.Query#setParameter(int, java.lang.Object) */
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#setParameter(int, java.lang.Object)
*/
@Override
public Query setParameter(int position, Object value)
{
kunderaQuery.setParameter(position, value);
return this;
}
/*
* @see javax.persistence.Query#setParameter(java.lang.String,
* java.util.Date, javax.persistence.TemporalType)
*/
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#setParameter(java.lang.String,
* java.util.Date, javax.persistence.TemporalType)
*/
@Override
public Query setParameter(String name, Date value, TemporalType temporalType)
{
// Purpose of temporal type is to set value based on temporal type.
throw new UnsupportedOperationException("setParameter is unsupported by Kundera");
}
/*
* @see javax.persistence.Query#setParameter(java.lang.String,
* java.util.Calendar, javax.persistence.TemporalType)
*/
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#setParameter(java.lang.String,
* java.util.Calendar, javax.persistence.TemporalType)
*/
@Override
public Query setParameter(String name, Calendar value, TemporalType temporalType)
{
throw new UnsupportedOperationException("setParameter is unsupported by Kundera");
}
/*
* @see javax.persistence.Query#setParameter(int, java.util.Date,
* javax.persistence.TemporalType)
*/
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#setParameter(int, java.util.Date,
* javax.persistence.TemporalType)
*/
@Override
public Query setParameter(int position, Date value, TemporalType temporalType)
{
throw new UnsupportedOperationException("setParameter is unsupported by Kundera");
}
/*
* @see javax.persistence.Query#setParameter(int, java.util.Calendar,
* javax.persistence.TemporalType)
*/
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#setParameter(int, java.util.Calendar,
* javax.persistence.TemporalType)
*/
@Override
public Query setParameter(int position, Calendar value, TemporalType temporalType)
{
throw new UnsupportedOperationException("setParameter is unsupported by Kundera");
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#getMaxResults()
*/
@Override
public int getMaxResults()
{
return maxResult;
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#getFirstResult()
*/
@Override
public int getFirstResult()
{
throw new UnsupportedOperationException("getFirstResult is unsupported by Kundera");
}
/**
* Returns a {@link Map} containing query hints set by user
*/
@Override
public Map<String, Object> getHints()
{
return hints;
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#setParameter(javax.persistence.Parameter,
* java.lang.Object)
*/
@Override
public <T> Query setParameter(Parameter<T> paramParameter, T paramT)
{
if (!getParameters().contains(paramParameter))
{
throw new IllegalArgumentException("parameter does not correspond to a parameter of the query");
}
if (paramParameter.getName() != null)
{
kunderaQuery.setParameter(paramParameter.getName(), paramT);
}
else
{
kunderaQuery.setParameter(paramParameter.getPosition(), paramT);
}
return this;
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#setParameter(javax.persistence.Parameter,
* java.util.Calendar, javax.persistence.TemporalType)
*/
@Override
public Query setParameter(Parameter<Calendar> paramParameter, Calendar paramCalendar, TemporalType paramTemporalType)
{
throw new UnsupportedOperationException("setParameter is unsupported by Kundera");
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#setParameter(javax.persistence.Parameter,
* java.util.Date, javax.persistence.TemporalType)
*/
@Override
public Query setParameter(Parameter<Date> paramParameter, Date paramDate, TemporalType paramTemporalType)
{
throw new UnsupportedOperationException("setParameter is unsupported by Kundera");
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#getParameters()
*/
@Override
public Set<Parameter<?>> getParameters()
{
if (parameters == null)
{
parameters = kunderaQuery.getParameters();
}
return parameters;
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#getParameter(java.lang.String)
*/
@Override
public Parameter<?> getParameter(String paramString)
{
onNativeCondition();
getParameters();
return getParameterByName(paramString);
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#getParameter(java.lang.String,
* java.lang.Class)
*/
@Override
public <T> Parameter<T> getParameter(String paramString, Class<T> paramClass)
{
onNativeCondition();
Parameter parameter = getParameterByName(paramString);
return onTypeCheck(paramClass, parameter);
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#getParameter(int)
*/
@Override
public Parameter<?> getParameter(int paramInt)
{
onNativeCondition();
getParameters();
return getParameterByOrdinal(paramInt);
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#getParameter(int, java.lang.Class)
*/
@Override
public <T> Parameter<T> getParameter(int paramInt, Class<T> paramClass)
{
onNativeCondition();
getParameters();
Parameter parameter = getParameterByOrdinal(paramInt);
return onTypeCheck(paramClass, parameter);
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#isBound(javax.persistence.Parameter)
*/
@Override
public boolean isBound(Parameter<?> paramParameter)
{
return kunderaQuery.isBound(paramParameter);
}
/*
* (non-Javadoc)
*
* @see
* javax.persistence.Query#getParameterValue(javax.persistence.Parameter)
*/
@Override
public <T> T getParameterValue(Parameter<T> paramParameter)
{
Object value = kunderaQuery.getClauseValue(paramParameter);
if (value == null)
{
throw new IllegalStateException("parameter has not been bound" + paramParameter);
}
return (T) value;
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#getParameterValue(java.lang.String)
*/
@Override
public Object getParameterValue(String paramString)
{
return onParameterValue(":" + paramString);
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#getParameterValue(int)
*/
@Override
public Object getParameterValue(int paramInt)
{
return onParameterValue("?" + paramInt);
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#getFlushMode()
*/
@Override
public FlushModeType getFlushMode()
{
throw new UnsupportedOperationException("getFlushMode is unsupported by Kundera");
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#setLockMode(javax.persistence.LockModeType)
*/
@Override
public Query setLockMode(LockModeType paramLockModeType)
{
throw new UnsupportedOperationException("setLockMode is unsupported by Kundera");
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#getLockMode()
*/
@Override
public LockModeType getLockMode()
{
throw new UnsupportedOperationException("getLockMode is unsupported by Kundera");
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Query#unwrap(java.lang.Class)
*/
@Override
public <T> T unwrap(Class<T> paramClass)
{
try
{
return (T) this;
}
catch (ClassCastException ccex)
{
throw new PersistenceException("Provider does not support the call for class type:[" + paramClass + "]");
}
}
/**
* Returns specific parameter instance for given name
*
* @param name
* parameter name.
*
* @return parameter
*/
private Parameter getParameterByName(String name)
{
if (getParameters() != null)
{
for (Parameter p : parameters)
{
if (name.equals(p.getName()))
{
return p;
}
}
}
return null;
}
/**
* Returns parameter by ordinal
*
* @param position
* position
* @return parameter instance.
*/
private Parameter getParameterByOrdinal(Integer position)
{
for (Parameter p : parameters)
{
if (position.equals(p.getPosition()))
{
return p;
}
}
return null;
}
/**
* Method to handle get/set Parameter supplied for native query.
*/
private void onNativeCondition()
{
ApplicationMetadata appMetadata = kunderaMetadata.getApplicationMetadata();
if (appMetadata.isNative(getJPAQuery()))
{
throw new IllegalStateException(
"invoked on a native query when the implementation does not support this use");
}
}
/**
* Validated parameter's class with input paramClass. Returns back parameter
* if it matches, else throws an {@link IllegalArgumentException}.
*
* @param <T>
* type of class.
* @param paramClass
* expected class type.
* @param parameter
* parameter
* @return parameter if it matches, else throws an
* {@link IllegalArgumentException}.
*/
private <T> Parameter<T> onTypeCheck(Class<T> paramClass, Parameter<T> parameter)
{
if (parameter != null && parameter.getParameterType() != null
&& parameter.getParameterType().equals(paramClass))
{
return parameter;
}
throw new IllegalArgumentException(
"The parameter of the specified name does not exist or is not assignable to the type");
}
/**
* Returns parameter value.
*
* @param paramString
* parameter as string.
*
* @return value of parameter.
*/
private List<Object> onParameterValue(String paramString)
{
List<Object> value = kunderaQuery.getClauseValue(paramString);
if (value == null)
{
throw new IllegalStateException("parameter has not been bound" + paramString);
}
return value;
}
protected String[] getColumns(final String[] columns, final EntityMetadata m)
{
List<String> columnAsList = new ArrayList<String>();
if (columns != null && columns.length > 0)
{
MetamodelImpl metaModel = (MetamodelImpl) kunderaMetadata.getApplicationMetadata().getMetamodel(
m.getPersistenceUnit());
EntityType entity = metaModel.entity(m.getEntityClazz());
for (int i = 1; i < columns.length; i++)
{
if (columns[i] != null)
{
Attribute col = entity.getAttribute(columns[i]);
if (col == null)
{
throw new QueryHandlerException("column type is null for: " + columns);
}
columnAsList.add(((AbstractAttribute) col).getJPAColumnName());
}
}
}
return columnAsList.toArray(new String[] {});
}
public void setFetchSize(Integer fetchsize)
{
this.fetchSize = fetchsize;
}
public Integer getFetchSize()
{
return this.fetchSize;
}
public void applyTTL(int ttlInSeconds)
{
this.ttl = ttlInSeconds;
}
public abstract void close();
public abstract <E> Iterator<E> iterate();
/**
* Handle post even callbacks.
*
*/
protected void handlePostEvent()
{
EntityMetadata metadata = getEntityMetadata();
if (!kunderaQuery.isDeleteUpdate())
{
persistenceDelegeator.getEventDispatcher().fireEventListeners(metadata, null, PostLoad.class);
}
}
/**
* Returns collection of fetched entities.
*
* @return
*/
protected List fetch()
{
EntityMetadata metadata = getEntityMetadata();
Client client = persistenceDelegeator.getClient(metadata);
List results = isRelational(metadata) ? recursivelyPopulateEntities(metadata, client) : populateEntities(
metadata, client);
return results;
}
protected void onValidateSingleResult(List results)
{
if (results == null || results.isEmpty())
{
log.error("No result found for {} ", kunderaQuery.getJPAQuery());
throw new NoResultException("No result found!");
}
if (results.size() > 1)
{
log.error("Non unique results found for query {} ", kunderaQuery.getJPAQuery());
throw new NonUniqueResultException("Containing more than one result!");
}
}
protected Object onReturnResults(List results)
{
onValidateSingleResult(results);
return results.get(0);
}
/**
* Returns true, if associated entity holds relational references(e.g. @OneToMany
* etc.) else false.
*
* @param m
* entity metadata
*
* @return true, if holds relation else false
*/
private boolean isRelational(EntityMetadata m)
{
// if related via join table OR contains relations.
return m.isRelationViaJoinTable() || (m.getRelationNames() != null && (!m.getRelationNames().isEmpty()));
}
/**
* If returned collection of object holds a reference to
*
* @param results
*/
private void assignReferenceToProxy(List results)
{
if (results != null)
{
for (Object obj : results)
{
kunderaMetadata.getCoreMetadata().getLazyInitializerFactory().setProxyOwners(getEntityMetadata(), obj);
}
}
}
}