All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.persistence.queries.ResultSetMappingQuery Maven / Gradle / Ivy

There is a newer version: 5.0.0-B03
Show newest version
/*
 * Copyright (c) 1998, 2024 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 v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     02/08/2012-2.4 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     06/20/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     07/13/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     08/24/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
//     09/27/2012-2.5 Guy Pelletier
//       - 350487: JPA 2.1 Specification defined support for Stored Procedure Calls
package org.eclipse.persistence.queries;

import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.internal.databaseaccess.DatabaseCall;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.sessions.DatabaseRecord;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;

/**
 * 

Purpose: * Concrete class to perform read using raw SQL and the SQLResultSetMapping. * *

Responsibilities: * Execute a selecting raw SQL string. * Returns a List of results. Each item in the list will be another list * consisting of the expected populated return types in the order they were * specified in the SQLResultSetMapping * * @see SQLResultSetMapping * @author Gordon Yorke * @since TopLink Java Essentials */ public class ResultSetMappingQuery extends ObjectBuildingQuery { protected boolean isExecuteCall; protected boolean returnNameValuePairs = false; protected Vector resultRows; protected List resultSetMappingNames = new ArrayList<>(); protected List resultSetMappings = new ArrayList<>(); /** * PUBLIC: * Initialize the state of the query. */ public ResultSetMappingQuery() { super(); } /** * PUBLIC: * Initialize the query to use the specified call. */ public ResultSetMappingQuery(Call call) { this(); setCall(call); } /** * PUBLIC: * Initialize the query to use the specified call and SQLResultSetMapping */ public ResultSetMappingQuery(Call call, String sqlResultSetMappingName) { this(); setCall(call); this.resultSetMappingNames.add(sqlResultSetMappingName); } /** * PUBLIC: * This will be the SQLResultSetMapping that is used by this query to process * the database results */ public void addSQLResultSetMapping(SQLResultSetMapping resultSetMapping){ this.resultSetMappings.add(resultSetMapping); this.resultSetMappingNames.add(resultSetMapping.getName()); } /** * PUBLIC: * Add a SQLResultSetMapping that is used by this query to process the * database results. */ public void addSQLResultSetMappingName(String name){ if (name == null) { throw new IllegalArgumentException(ExceptionLocalization.buildMessage("null_sqlresultsetmapping_in_query")); } this.resultSetMappingNames.add(name); } /** * INTERNAL: *

This method is called by the object builder when building an original. * It will cause the original to be cached in the query results if the query * is set to do so. */ @Override public void cacheResult(Object unwrappedOriginal) { Object cachableObject = unwrappedOriginal; if (shouldUseWrapperPolicy()){ cachableObject = getSession().wrapObject(unwrappedOriginal); } setTemporaryCachedQueryResults(cachableObject); } /** * INTERNAL: * Convert all the class-name-based settings in this ResultSetMapping to actual class-based * settings. This method is used when converting a project that has been built * with class names to a project with classes. */ @Override public void convertClassNamesToClasses(ClassLoader classLoader){ for (SQLResultSetMapping mapping : this.resultSetMappings) { mapping.convertClassNamesToClasses(classLoader); } } /** * Indicates whether or not to return populated DatabaseRecord(s) * as opposed to raw data when an SQLResultSetMapping is not set. */ public boolean shouldReturnNameValuePairs() { return returnNameValuePairs; } /** * Set the flag that indicates whether or not to return populated * DatabaseRecord(s) as opposed to raw data when an * SQLResultSetMapping is not set. */ public void setShouldReturnNameValuePairs(boolean returnNameValuePairs) { this.returnNameValuePairs = returnNameValuePairs; } /** * PUBLIC: * This will be the SQLResultSetMapping that is used by this query to process * the database results */ public void setSQLResultSetMapping(SQLResultSetMapping resultSetMapping) { addSQLResultSetMapping(resultSetMapping); } /** * PUBLIC: * This will be the SQLResultSetMappings that are used by this query to * process the database results */ public void setSQLResultSetMappings(List resultSetMappings) { this.resultSetMappings = resultSetMappings; } /** * PUBLIC: * This will be the SQLResultSetMapping that is used by this query to process * the database results */ public void setSQLResultSetMappingName(String name) { addSQLResultSetMappingName(name); } /** * PUBLIC: * This will be the SQLResult */ public void setSQLResultSetMappingNames(List names) { if (names.isEmpty()) { throw new IllegalArgumentException(ExceptionLocalization.buildMessage("null_sqlresultsetmapping_in_query")); } this.resultSetMappingNames = names; } /** * INTERNAL: * This method is used to build the results. Interpreting the * SQLResultSetMapping(s). */ public List buildObjectsFromRecords(List databaseRecords){ if (getSQLResultSetMappings().size() > 1) { int numberOfRecords = databaseRecords.size(); List results = new ArrayList(numberOfRecords); for (int recordIndex = 0; recordIndex < numberOfRecords; recordIndex++) { Object records = databaseRecords.get(recordIndex); if (records instanceof Map recordsMap) { // We have a map keyed on named ref_cursors for (Object list : recordsMap.values()) { results.add(buildObjectsFromRecords((List) list, getSQLResultSetMappings().get(recordIndex))); recordIndex++; } } else { // Regular list of records, iterate through them. results.add(buildObjectsFromRecords((List) records, getSQLResultSetMappings().get(recordIndex))); } } return results; } else { return buildObjectsFromRecords(databaseRecords, getSQLResultSetMapping()); } } /** * INTERNAL: * This method is used to build the results with the SQLResultSetMapping * at the given index. */ public List buildObjectsFromRecords(List databaseRecords, int index){ if (getSQLResultSetMappings().isEmpty()) { return buildObjectsFromRecords(databaseRecords, null); } else { return buildObjectsFromRecords(databaseRecords, getSQLResultSetMappings().get(index)); } } /** * INTERNAL: * This method is used to build the results. Interpreting the SQLResultSetMapping. */ protected List buildObjectsFromRecords(List databaseRecords, SQLResultSetMapping mapping) { int numberOfRecords = databaseRecords.size(); List results = new ArrayList(numberOfRecords); if (mapping == null) { if (shouldReturnNameValuePairs()) { return databaseRecords; } for (Iterator iterator = databaseRecords.iterator(); iterator.hasNext();) { DatabaseRecord record = (DatabaseRecord)iterator.next(); results.add(record.values().toArray()); } } else { for (Iterator iterator = databaseRecords.iterator(); iterator.hasNext();) { if (mapping.getResults().size() > 1) { Object[] resultElement = new Object[mapping.getResults().size()]; DatabaseRecord record = (DatabaseRecord)iterator.next(); for (int i = 0; i < mapping.getResults().size(); i++) { resultElement[i] = mapping.getResults().get(i).getValueFromRecord(record, this); } results.add(resultElement); } else if (mapping.getResults().size() == 1) { DatabaseRecord record = (DatabaseRecord)iterator.next(); results.add(mapping.getResults().get(0).getValueFromRecord(record, this)); } else { return results; } } } return results; } /** * INTERNAL: * Executes the prepared query on the datastore. */ @Override public Object executeDatabaseQuery() throws DatabaseException { if (getSession().isUnitOfWork()) { UnitOfWorkImpl unitOfWork = (UnitOfWorkImpl)getSession(); // Note if a nested unit of work this will recursively start a // transaction early on the parent also. if (isLockQuery()) { if ((!unitOfWork.getCommitManager().isActive()) && (!unitOfWork.wasTransactionBegunPrematurely())) { unitOfWork.beginTransaction(); unitOfWork.setWasTransactionBegunPrematurely(true); } } if (unitOfWork.isNestedUnitOfWork()) { // execute in parent UOW then register normally here. UnitOfWorkImpl nestedUnitOfWork = (UnitOfWorkImpl)getSession(); setSession(nestedUnitOfWork.getParent()); Object result = executeDatabaseQuery(); setSession(nestedUnitOfWork); Object clone = registerIndividualResult(result, null, unitOfWork, null, null); if (shouldUseWrapperPolicy()) { clone = getDescriptor().getObjectBuilder().wrapObject(clone, unitOfWork); } return clone; } } session.validateQuery(this);// this will update the query with any settings if (getQueryId() == 0) { setQueryId(getSession().getNextQueryId()); } if (getCall().isExecuteUpdate()) { DatabaseCall call = ((StoredProcedureCall) getQueryMechanism().execute()); setExecutionTime(System.currentTimeMillis()); return call; } else { Vector rows = getQueryMechanism().executeSelect(); setExecutionTime(System.currentTimeMillis()); // If using 1-m joins, must set all rows. return buildObjectsFromRecords(rows); } } /** * PUBLIC: * Return true if there are results set mappings associated with this query. */ public boolean hasResultSetMappings() { return ! getSQLResultSetMappings().isEmpty(); } /** * PUBLIC: Return true if this is a result set mapping query. */ @Override public boolean isResultSetMappingQuery() { return true; } /** * INTERNAL: * Prepare the receiver for execution in a session. */ @Override protected void prepare() { if ((!shouldMaintainCache()) && shouldRefreshIdentityMapResult()) { throw QueryException.refreshNotPossibleWithoutCache(this); } getQueryMechanism().prepare(); if (isExecuteCall) { getQueryMechanism().prepareExecute(); } else { getQueryMechanism().prepareExecuteSelect(); } } /** * PUBLIC: * This will be the SQLResultSetMapping that is used by this query to process * the database results */ public SQLResultSetMapping getSQLResultSetMapping() { if (resultSetMappings.isEmpty()) { if (resultSetMappingNames.isEmpty()) { return null; } else { return getSession().getProject().getSQLResultSetMapping(resultSetMappingNames.get(0)); } } return resultSetMappings.get(0); } /** * PUBLIC: * This will be the SQLResultSetMapping that is used by this query to process * the database results */ public List getSQLResultSetMappings() { if (this.resultSetMappings.isEmpty()) { ArrayList list = new ArrayList<>(); for (String resultSetMappingName : this.resultSetMappingNames) { list.add(getSession().getProject().getSQLResultSetMapping(resultSetMappingName)); } return list; } else { return resultSetMappings; } } /** * PUBLIC: * Return the result set mapping name. */ public String getSQLResultSetMappingName() { return this.resultSetMappingNames.get(0); } /** * PUBLIC: * Return the result set mapping name. */ public List getSQLResultSetMappingNames() { return this.resultSetMappingNames; } /** * PUBLIC: * Set to true if you the actual jdbc result set returned from query * execution. This will unprepare the query in case it was executed * previously for a getResultList() call instead (or vice versa) */ public void setIsExecuteCall(boolean isExecuteCall) { this.isExecuteCall = isExecuteCall; // Force the query to prepare. setIsPrepared(false); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy