
org.eclipse.persistence.internal.jpa.EJBQueryImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction 346465e
/*******************************************************************************
* Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
* Zoltan NAGY & tware - updated support for MaxRows
* 11/01/2010-2.2 Guy Pelletier
* - 322916: getParameter on Query throws NPE
* 11/09/2010-2.1 Michael O'Brien
* - 329089: PERF: EJBQueryImpl.setParamenterInternal() move indexOf check inside non-native block
******************************************************************************/
package org.eclipse.persistence.internal.jpa;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.FlushModeType;
import javax.persistence.LockModeType;
import javax.persistence.LockTimeoutException;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Parameter;
import javax.persistence.PersistenceException;
import javax.persistence.PessimisticLockException;
import javax.persistence.Query;
import javax.persistence.TemporalType;
import javax.persistence.TypedQuery;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.internal.helper.BasicTypeHelperImpl;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.jpa.parsing.JPQLParseTree;
import org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser;
import org.eclipse.persistence.internal.jpa.querydef.ParameterExpressionImpl;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.internal.queries.JPQLCallQueryMechanism;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.jpa.JpaEntityManager;
import org.eclipse.persistence.jpa.JpaQuery;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLStoredProcedureCall;
import org.eclipse.persistence.platform.database.oracle.plsql.PLSQLargument;
import org.eclipse.persistence.queries.Call;
import org.eclipse.persistence.queries.Cursor;
import org.eclipse.persistence.queries.DataModifyQuery;
import org.eclipse.persistence.queries.DataReadQuery;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ModifyQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.queries.ResultSetMappingQuery;
import org.eclipse.persistence.queries.StoredProcedureCall;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.sessions.Session;
/**
* Concrete JPA query class. The JPA query wraps a DatabaseQuery which is
* executed.
*/
public class EJBQueryImpl implements JpaQuery {
private static final int UNDEFINED = -1;
/**
* Wrapped native query. The query may be {@link #isShared}
*/
protected DatabaseQuery databaseQuery = null;
protected EntityManagerImpl entityManager = null;
protected String queryName = null;
protected Map parameterValues = null;
protected Map> parameters;
protected int firstResultIndex = UNDEFINED;
protected int maxResults = UNDEFINED;
protected LockModeType lockMode = null;
/**
* Stores if the wrapped query is shared, and requires cloning before being
* changed.
*/
protected boolean isShared;
/**
* Base constructor for EJBQueryImpl. Initializes basic variables.
*/
protected EJBQueryImpl(EntityManagerImpl entityManager) {
this.parameterValues = new HashMap();
this.entityManager = entityManager;
this.isShared = true;
}
/**
* Create an EJBQueryImpl with a DatabaseQuery.
*/
public EJBQueryImpl(DatabaseQuery query, EntityManagerImpl entityManager) {
this(entityManager);
this.databaseQuery = query;
}
/**
* Build an EJBQueryImpl based on the given jpql string.
*/
public EJBQueryImpl(String jpql, EntityManagerImpl entityManager) {
this(jpql, entityManager, false);
}
/**
* Create an EJBQueryImpl with either a query name or an jpql string.
*
* @param isNamedQuery
* determines whether to treat the queryDescription as jpql or a
* query name.
*/
public EJBQueryImpl(String queryDescription, EntityManagerImpl entityManager, boolean isNamedQuery) {
this(entityManager);
if (isNamedQuery) {
this.queryName = queryDescription;
} else {
if (databaseQuery == null) {
databaseQuery = buildEJBQLDatabaseQuery(queryDescription, this.entityManager.getDatabaseSession());
}
}
}
/**
* Internal method to change the wrapped query to a DataModifyQuery if
* necessary. When created, the query is created as a DataReadQuery as it is
* unknown if it is a SELECT or UPDATE. Note that this prevents the original
* named query from every being prepared.
*/
protected void setAsSQLModifyQuery() {
if (getDatabaseQueryInternal().isDataReadQuery()) {
DataModifyQuery query = new DataModifyQuery();
query.setIsUserDefined(this.databaseQuery.isUserDefined());
query.copyFromQuery(this.databaseQuery);
// Need to clone call, in case was executed as read.
query.setDatasourceCall((Call) this.databaseQuery.getDatasourceCall().clone());
this.databaseQuery = query;
}
}
/**
* Internal method to change the wrapped query to a DataReadQuery if
* necessary. This should never occur, but could possibly if the same query
* was executed as executeUpdate() then as getResultList(). Note that the
* initial conversion to modify would loose any read settings that had been
* set.
*/
protected void setAsSQLReadQuery() {
if (getDatabaseQueryInternal().isDataModifyQuery()) {
DataReadQuery query = new DataReadQuery();
query.setResultType(DataReadQuery.AUTO);
query.setIsUserDefined(databaseQuery.isUserDefined());
query.copyFromQuery(this.databaseQuery);
this.databaseQuery = query;
}
}
/**
* Build a DatabaseQuery from an jpql string.
*
* @param jpql
* @param session
* the session to get the descriptors for this query for.
* @return a DatabaseQuery representing the given jpql.
*/
public static DatabaseQuery buildEJBQLDatabaseQuery(String jpql, Session session) {
return buildEJBQLDatabaseQuery(null, jpql, session, null, null, session.getDatasourcePlatform().getConversionManager().getLoader());
}
/**
* Build a DatabaseQuery from an JPQL string.
*
* @param jpql
* the JPQL string.
* @param flushOnExecute
* flush the unit of work before executing the query.
* @param session
* the session to get the descriptors for this query for.
* @param hints
* a list of hints to be applied to the query.
* @return a DatabaseQuery representing the given jpql.
*/
public static DatabaseQuery buildEJBQLDatabaseQuery(String queryName, String jpql, Session session, Enum lockMode, Map hints, ClassLoader classLoader) {
// PERF: Check if the JPQL has already been parsed.
// Only allow queries with default properties to be parse cached.
boolean isCacheable = (queryName == null) && (hints == null);
DatabaseQuery databaseQuery = null;
if (isCacheable) {
databaseQuery = (DatabaseQuery) session.getProject().getJPQLParseCache().get(jpql);
}
if ((databaseQuery == null) || (!databaseQuery.isPrepared())) {
JPQLParseTree parseTree = JPQLParser.buildParseTree(queryName, jpql);
parseTree.setClassLoader(classLoader);
databaseQuery = parseTree.createDatabaseQuery();
databaseQuery.setJPQLString(jpql);
parseTree.populateQuery(databaseQuery, (AbstractSession) session);
// If the query uses fetch joins, need to use JPA default of not
// filtering duplicates.
if (databaseQuery.isReadAllQuery()) {
ReadAllQuery readAllQuery = (ReadAllQuery) databaseQuery;
if (readAllQuery.hasJoining() && (readAllQuery.getDistinctState() == ReadAllQuery.DONT_USE_DISTINCT)) {
readAllQuery.setShouldFilterDuplicates(false);
}
}
// Bug#4646580 Add arguments to query.
parseTree.addParametersToQuery(databaseQuery);
((JPQLCallQueryMechanism) databaseQuery.getQueryMechanism()).getJPQLCall().setIsParsed(true);
// Apply the lock mode.
if (lockMode != null && !lockMode.name().equals(ObjectLevelReadQuery.NONE)) {
if (databaseQuery.isObjectLevelReadQuery()) {
// If setting the lock mode returns true, we were unable to
// set the lock mode, throw an exception.
if (((ObjectLevelReadQuery) databaseQuery).setLockModeType(lockMode.name(), (AbstractSession)session)) {
throw new PersistenceException(ExceptionLocalization.buildMessage("ejb30-wrong-lock_called_without_version_locking-index", null));
}
} else {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("invalid_lock_query", (Object[]) null));
}
}
// Apply any query hints.
databaseQuery = applyHints(hints, databaseQuery, classLoader, (AbstractSession)session);
// If a primary key query, switch to read-object to allow cache hit.
if (databaseQuery.isReadAllQuery() && !databaseQuery.isReportQuery() && ((ReadAllQuery)databaseQuery).shouldCheckCache()) {
ReadAllQuery readQuery = (ReadAllQuery)databaseQuery;
if ((readQuery.getContainerPolicy().getContainerClass() == ContainerPolicy.getDefaultContainerClass())
&& (!readQuery.hasHierarchicalExpressions())) {
databaseQuery.checkDescriptor((AbstractSession)session);
Expression selectionCriteria = databaseQuery.getSelectionCriteria();
if ((selectionCriteria) != null
&& databaseQuery.getDescriptor().getObjectBuilder().isPrimaryKeyExpression(true, selectionCriteria, (AbstractSession)session)) {
ReadObjectQuery newQuery = new ReadObjectQuery();
newQuery.copyFromQuery(databaseQuery);
databaseQuery = newQuery;
}
}
}
if (isCacheable) {
// Prepare query as hint may cause cloning (but not un-prepare
// as in read-only).
databaseQuery.prepareCall(session, new DatabaseRecord());
session.getProject().getJPQLParseCache().put(jpql, databaseQuery);
}
}
return databaseQuery;
}
/**
* Build a ReadAllQuery from a class and sql string.
*/
public static DatabaseQuery buildSQLDatabaseQuery(Class resultClass, String sqlString, ClassLoader classLoader, AbstractSession session) {
return buildSQLDatabaseQuery(resultClass, sqlString, null, classLoader, session);
}
/**
* Build a ReadAllQuery for class and sql string.
*
* @param hints
* a list of hints to be applied to the query.
*/
public static DatabaseQuery buildSQLDatabaseQuery(Class resultClass, String sqlString, Map hints, ClassLoader classLoader, AbstractSession session) {
ReadAllQuery query = new ReadAllQuery(resultClass);
query.setSQLString(sqlString);
query.setIsUserDefined(true);
// apply any query hints
return applyHints(hints, query, classLoader, session);
}
/**
* Build a ResultSetMappingQuery from a sql result set mapping name and sql
* string.
*/
public static DatabaseQuery buildSQLDatabaseQuery(String sqlResultSetMappingName, String sqlString, ClassLoader classLoader, AbstractSession session) {
return buildSQLDatabaseQuery(sqlResultSetMappingName, sqlString, null, classLoader, session);
}
/**
* Build a ResultSetMappingQuery from a sql result set mapping name and sql
* string.
*
* @param hints
* a list of hints to be applied to the query.
*/
public static DatabaseQuery buildSQLDatabaseQuery(String sqlResultSetMappingName, String sqlString, Map hints, ClassLoader classLoader, AbstractSession session) {
ResultSetMappingQuery query = new ResultSetMappingQuery();
query.setSQLResultSetMappingName(sqlResultSetMappingName);
query.setSQLString(sqlString);
query.setIsUserDefined(true);
// apply any query hints
return applyHints(hints, query, classLoader, session);
}
/**
* Build a ReadAllQuery from a class and stored procedure call.
*/
public static DatabaseQuery buildStoredProcedureQuery(Class resultClass, StoredProcedureCall call, Map hints, ClassLoader classLoader, AbstractSession session) {
DatabaseQuery query = new ReadAllQuery(resultClass);
query.setCall(call);
query.setIsUserDefined(true);
// apply any query hints
query = applyHints(hints, query, classLoader, session);
// apply any query arguments
applyArguments(call, query);
return query;
}
/**
* Build a ResultSetMappingQuery from a sql result set mapping name and a
* stored procedure call.
*/
public static DatabaseQuery buildStoredProcedureQuery(StoredProcedureCall call, Map hints, ClassLoader classLoader, AbstractSession session) {
DataReadQuery query = new DataReadQuery();
query.setResultType(DataReadQuery.AUTO);
query.setCall(call);
query.setIsUserDefined(true);
// apply any query hints
DatabaseQuery hintQuery = applyHints(hints, query, classLoader, session);
// apply any query arguments
applyArguments(call, hintQuery);
return hintQuery;
}
/**
* Build a ResultSetMappingQuery from a sql result set mapping name and a
* stored procedure call.
*/
public static DatabaseQuery buildStoredProcedureQuery(String sqlResultSetMappingName, StoredProcedureCall call, Map hints, ClassLoader classLoader, AbstractSession session) {
ResultSetMappingQuery query = new ResultSetMappingQuery();
query.setSQLResultSetMappingName(sqlResultSetMappingName);
query.setCall(call);
query.setIsUserDefined(true);
// apply any query hints
DatabaseQuery hintQuery = applyHints(hints, query, classLoader, session);
// apply any query arguments
applyArguments(call, hintQuery);
return hintQuery;
}
/**
* Build a DataReadQuery from a sql string.
*/
public static DatabaseQuery buildSQLDatabaseQuery(String sqlString, ClassLoader classLoader, AbstractSession session) {
return buildSQLDatabaseQuery(sqlString, new HashMap(), classLoader, session);
}
/**
* Build a DataReadQuery from a sql string.
*/
public static DatabaseQuery buildSQLDatabaseQuery(String sqlString, Map hints, ClassLoader classLoader, AbstractSession session) {
DataReadQuery query = new DataReadQuery();
query.setResultType(DataReadQuery.AUTO);
query.setSQLString(sqlString);
query.setIsUserDefined(true);
// apply any query hints
return applyHints(hints, query, classLoader, session);
}
/**
* Execute a ReadQuery by assigning the stored parameter values and running
* it in the database
*
* @return the results of the query execution
*/
protected Object executeReadQuery() {
List parameterValues = processParameters();
// TODO: the following performFlush() call is a temporary workaround for
// bug 4752493:
// CTS: INMEMORY QUERYING IN EJBQUERY BROKEN DUE TO CHANGE TO USE
// REPORTQUERY.
// Ideally we should only flush in case the selectionExpression can't be
// conformed in memory.
// There are two alternative ways to implement that:
// 1. Try running the query with conformInUOW flag first - if it fails
// with
// QueryException.cannotConformExpression then flush and run the query
// again -
// now without conforming.
// 2. Implement a new isComformable method on Expression which would
// determine whether the expression
// could be conformed in memory, flush only in case it returns false.
// Note that doesConform method currently implemented on Expression
// requires object(s) to be confirmed as parameter(s).
// The new isComformable method should not take any objects as
// parameters,
// it should return false if there could be such an object that
// passed to doesConform causes it to throw
// QueryException.cannotConformExpression -
// and true otherwise.
boolean shouldResetConformResultsInUnitOfWork = false;
DatabaseQuery query = getDatabaseQueryInternal();
boolean isObjectLevelReadQuery = query.isObjectLevelReadQuery();
if (isFlushModeAUTO() && (!isObjectLevelReadQuery || !((ObjectLevelReadQuery)query).isReadOnly())) {
performPreQueryFlush();
if (isObjectLevelReadQuery) {
if (((ObjectLevelReadQuery)query).shouldConformResultsInUnitOfWork()) {
cloneSharedQuery();
query = getDatabaseQueryInternal();
((ObjectLevelReadQuery)query).setCacheUsage(ObjectLevelReadQuery.UseDescriptorSetting);
shouldResetConformResultsInUnitOfWork = true;
}
}
}
// Set a pessimistic locking on the query if specified.
if (this.lockMode != null) {
// We need to throw TransactionRequiredException if there is no
// active transaction
this.entityManager.checkForTransaction(true);
// The lock mode setters and getters validate the query type
// so should be safe to make the casting.
cloneSharedQuery();
query = getDatabaseQueryInternal();
// Set the lock mode (the session is passed in to do some validation
// checks)
// If the return value from the set returns true, it indicates that
// we were unable to set the lock mode.
if (((ObjectLevelReadQuery)query).setLockModeType(lockMode.name(), (AbstractSession) getActiveSession())) {
throw new PersistenceException(ExceptionLocalization.buildMessage("ejb30-wrong-lock_called_without_version_locking-index", null));
}
}
Session session = getActiveSession();
try {
// in case it's a user-defined query
if (query.isUserDefined()) {
// and there is an active transaction
if (this.entityManager.checkForTransaction(false) != null) {
// verify whether uow has begun early transaction
if (session.isUnitOfWork() && !((UnitOfWorkImpl)session).wasTransactionBegunPrematurely()) {
// uow begins early transaction in case it hasn't
// already begun.
// TODO: This is not good, it means that no SQL queries
// can ever use the cache,
// using isUserDefined to mean an SQL query is also
// wrong.
((UnitOfWorkImpl)session).beginEarlyTransaction();
}
}
}
// Execute the query and return the result.
return session.executeQuery(query, parameterValues);
} catch (DatabaseException e) {
throw getDetailedException(e);
} catch (RuntimeException e) {
setRollbackOnly();
throw e;
} finally {
this.lockMode = null;
if (shouldResetConformResultsInUnitOfWork) {
((ObjectLevelReadQuery)query).conformResultsInUnitOfWork();
}
}
}
/**
* Execute an update or delete statement.
*
* @return the number of entities updated or deleted
*/
public int executeUpdate() {
// bug51411440: need to throw IllegalStateException if query
// executed on closed em
this.entityManager.verifyOpenWithSetRollbackOnly();
try {
setAsSQLModifyQuery();
// bug:4294241, only allow modify queries - UpdateAllQuery preferred
if (!(getDatabaseQueryInternal() instanceof ModifyQuery)) {
throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_execute_update"));
}
// need to throw TransactionRequiredException if there is no active
// transaction
entityManager.checkForTransaction(true);
// fix for bug:4288845, did not add the parameters to the query
List parameterValues = processParameters();
if (isFlushModeAUTO()) {
performPreQueryFlush();
}
Integer changedRows = (Integer) getActiveSession().executeQuery(databaseQuery, parameterValues);
return changedRows.intValue();
} catch (PersistenceException exception) {
setRollbackOnly();
throw exception;
} catch (IllegalStateException exception) {
setRollbackOnly();
throw exception;
}catch (RuntimeException exception) {
setRollbackOnly();
throw new PersistenceException(exception);
}
}
/**
* Return the wrapped {@link DatabaseQuery} ensuring that if it
* {@link #isShared} it is cloned before returning to prevent corruption of
* the query cache.
*
* @see #getDatabaseQueryInternal()
*/
public DatabaseQuery getDatabaseQuery() {
cloneSharedQuery();
return getDatabaseQueryInternal();
}
/**
* INTERNAL: Return the cached database query for this EJBQueryImpl. If the
* query is a named query and it has not yet been looked up, the query will
* be looked up and stored as the cached query.
*/
public DatabaseQuery getDatabaseQueryInternal() {
if ((this.queryName != null) && (this.databaseQuery == null)) {
// need error checking and appropriate exception for non-existing
// query
this.databaseQuery = this.entityManager.getDatabaseSession().getQuery(this.queryName);
if (this.databaseQuery != null) {
if (!this.databaseQuery.isPrepared()) {
// prepare the query before cloning, this ensures we do not
// have to continually prepare on each usage
this.databaseQuery.prepareCall(this.entityManager.getDatabaseSession(), new DatabaseRecord());
}
} else {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("unable_to_find_named_query", new Object[] { this.queryName }));
}
}
return this.databaseQuery;
}
/**
* Given a DatabaseException, this method will determine if we should
* throw a different more specific exception like a lock timeout exception.
*/
protected RuntimeException getDetailedException(DatabaseException e) {
// If we catch a database exception as a result of executing a
// pessimistic locking query we need to ask the platform which
// JPA 2.0 locking exception we should throw. It will be either
// be a PessimisticLockException or a LockTimeoutException (if
// the query was executed using a wait timeout value)
if (this.lockMode != null && this.lockMode.name().contains(ObjectLevelReadQuery.PESSIMISTIC_)) {
// ask the platform if it is a lock timeout
if (getActiveSession().getPlatform().isLockTimeoutException(e)) {
return new LockTimeoutException(e);
} else {
return new PessimisticLockException(e);
}
} else {
setRollbackOnly();
return new PersistenceException(e);
}
}
/**
* Return the entityManager this query is tied to.
*/
public JpaEntityManager getEntityManager() {
return entityManager;
}
/**
* Return the internal map of parameters.
*/
protected Map> getInternalParameters() {
if (this.parameters == null) {
this.parameters = new HashMap>();
DatabaseQuery query = getDatabaseQueryInternal(); // Retrieve named
// query
int count = 0;
if (query.getArguments() != null && !query.getArguments().isEmpty()) {
for (String argName : query.getArguments()) {
Parameter> param = new ParameterExpressionImpl(null, query.getArgumentTypes().get(count), argName);
this.parameters.put(argName, param);
++count;
}
}
}
return this.parameters;
}
/**
* Get the current lock mode for the query.
*
* @return lock mode
* @throws IllegalStateException
* if not a Java Persistence query language SELECT query
*/
public LockModeType getLockMode() {
try {
entityManager.verifyOpen();
if (!getDatabaseQueryInternal().isReadQuery()) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("invalid_lock_query", (Object[]) null));
}
return this.lockMode;
} catch (RuntimeException e) {
setRollbackOnly();
throw e;
}
}
/**
* Non-standard method to return results of a ReadQuery that uses a Cursor.
*
* @return Cursor on results, either a CursoredStream, or ScrollableCursor
*/
public Cursor getResultCursor() {
// bug51411440: need to throw IllegalStateException if query executed on
// closed em
entityManager.verifyOpen();
setAsSQLReadQuery();
propagateResultProperties();
// bug:4297903, check container policy class and throw exception if its
// not the right type
if (getDatabaseQueryInternal() instanceof ReadAllQuery) {
if (!((ReadAllQuery) getDatabaseQueryInternal()).getContainerPolicy().isCursorPolicy()) {
Class containerClass = ((ReadAllQuery) getDatabaseQueryInternal()).getContainerPolicy().getContainerClass();
throw QueryException.invalidContainerClass(containerClass, Cursor.class);
}
} else if (getDatabaseQueryInternal() instanceof ReadObjectQuery) {
// bug:4300879, no support for ReadObjectQuery if a collection is required
throw QueryException.incorrectQueryObjectFound(getDatabaseQueryInternal(), ReadAllQuery.class);
} else if (!(getDatabaseQueryInternal() instanceof ReadQuery)) {
throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_get_result_collection"));
}
try {
Object result = executeReadQuery();
return (Cursor) result;
} catch (LockTimeoutException e) {
throw e;
} catch (RuntimeException e) {
setRollbackOnly();
throw e;
}
}
/**
* Non-standard method to return results of a ReadQuery that has a
* containerPolicy that returns objects as a collection rather than a List
*
* @return Collection of results
*/
public Collection getResultCollection() {
// bug51411440: need to throw IllegalStateException if query
// executed on closed em
this.entityManager.verifyOpenWithSetRollbackOnly();
setAsSQLReadQuery();
propagateResultProperties();
// bug:4297903, check container policy class and throw exception if its
// not the right type
DatabaseQuery query = getDatabaseQueryInternal();
try{
if (query.isReadAllQuery()) {
Class containerClass = ((ReadAllQuery) getDatabaseQueryInternal()).getContainerPolicy().getContainerClass();
if (!Helper.classImplementsInterface(containerClass, ClassConstants.Collection_Class)) {
throw QueryException.invalidContainerClass(containerClass, ClassConstants.Collection_Class);
}
} else if (query.isReadObjectQuery()) {
List resultList = new ArrayList();
Object result = executeReadQuery();
if (result != null) {
resultList.add(executeReadQuery());
}
return resultList;
} else if (!query.isReadQuery()) {
throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_get_result_collection"));
}
return (Collection) executeReadQuery();
} catch (LockTimeoutException exception) {
throw exception;
} catch (PersistenceException exception) {
setRollbackOnly();
throw exception;
} catch (IllegalStateException exception) {
setRollbackOnly();
throw exception;
} catch (RuntimeException exception) {
setRollbackOnly();
throw new PersistenceException(exception);
}
}
/**
* Execute the query and return the query results as a List.
*
* @return a list of the results
*/
public List getResultList() {
// bug51411440: need to throw IllegalStateException if query
// executed on closed em
this.entityManager.verifyOpenWithSetRollbackOnly();
try {
setAsSQLReadQuery();
propagateResultProperties();
// bug:4297903, check container policy class and throw exception if
// its not the right type
DatabaseQuery query = getDatabaseQueryInternal();
if (query.isReadAllQuery()) {
Class containerClass = ((ReadAllQuery) query).getContainerPolicy().getContainerClass();
if (!Helper.classImplementsInterface(containerClass, ClassConstants.List_Class)) {
throw QueryException.invalidContainerClass(containerClass, ClassConstants.List_Class);
}
} else if (query.isReadObjectQuery()) {
List resultList = new ArrayList();
Object result = executeReadQuery();
if (result != null) {
resultList.add(result);
}
return resultList;
} else if (!query.isReadQuery()) {
throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_get_result_list"));
}
return (List) executeReadQuery();
} catch (LockTimeoutException exception) {
throw exception;
} catch (PersistenceException exception) {
setRollbackOnly();
throw exception;
} catch (IllegalStateException exception) {
setRollbackOnly();
throw exception;
} catch (RuntimeException exception) {
setRollbackOnly();
throw new PersistenceException(exception);
}
}
/**
* Execute a query that returns a single result.
*
* @return the result
* @throws javax.persistence.EntityNotFoundException
* if there is no result
* @throws javax.persistence.NonUniqueResultException
* if more than one result
*/
public X getSingleResult() {
boolean rollbackOnException = true;
// bug51411440: need to throw IllegalStateException if query
// executed on closed em
this.entityManager.verifyOpenWithSetRollbackOnly();
try {
setAsSQLReadQuery();
propagateResultProperties();
// This API is used to return non-List results, so no other validation is done.
// It could be Cursor or other Collection or Map type.
if (!(getDatabaseQueryInternal().isReadQuery())) {
throw new IllegalStateException(ExceptionLocalization.buildMessage("incorrect_query_for_get_single_result"));
}
Object result = executeReadQuery();
if (result instanceof List) {
List results = (List) result;
if (results.isEmpty()) {
rollbackOnException = false;
throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", (Object[]) null));
} else if (results.size() > 1) {
rollbackOnException = false;
throwNonUniqueResultException(ExceptionLocalization.buildMessage("too_many_results_for_get_single_result", (Object[]) null));
}
return (X) results.get(0);
} else {
if (result == null) {
rollbackOnException = false;
throwNoResultException(ExceptionLocalization.buildMessage("no_entities_retrieved_for_get_single_result", (Object[]) null));
}
return (X) result;
}
} catch (LockTimeoutException exception) {
throw exception;
} catch (PersistenceException exception) {
if (rollbackOnException) {
setRollbackOnly();
}
throw exception;
} catch (IllegalStateException exception) {
setRollbackOnly();
throw exception;
} catch (RuntimeException exception) {
setRollbackOnly();
throw new PersistenceException(exception);
}
}
/**
* Internal method to add the parameters values to the query prior to
* execution. Returns a list of parameter values in the order the parameters
* are defined for the databaseQuery.
*/
protected List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy