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

org.apache.openjpa.persistence.StoredProcedureQueryImpl Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.openjpa.persistence;

import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
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.ParameterMode;
import javax.persistence.StoredProcedureQuery;
import javax.persistence.TemporalType;

import org.apache.openjpa.kernel.DelegatingResultList;
import org.apache.openjpa.kernel.QueryResultCallback;
import org.apache.openjpa.lib.rop.ResultList;
import org.apache.openjpa.lib.rop.ResultObjectProvider;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.MultiQueryMetaData;
import org.apache.openjpa.util.RuntimeExceptionTranslator;
import org.apache.openjpa.util.UserException;

/**
 * Implements Store Procedure based query for JPA facade.
 * 
* A {@link StoredProcedureQuery stored procedure query} differs from other query types because it may return * more than one result set, apart from an optional update count, whereas the traditional query processing in OpenJPA * via the abstractions of {@link ResultObjectProvider} and {@link org.apache.openjpa.jdbc.sql.Result} * assumed that a query will return its * result in a single list. *
* This query resorts to a callback mechanism, where the execution of the query returns not a result, but a * {@link QueryResultCallback callback object} that can be used to callback to OpenJPA kernel to get a series of * results via the traditional result processing pathway. * * @author Pinaki Poddar * @author Romain Manni-Bucau */ // TODO: add lock public class StoredProcedureQueryImpl implements StoredProcedureQuery { private static final Localizer _loc = Localizer.forPackage(QueryImpl.class); private final String _name; private final QueryImpl _delegate; private final MultiQueryMetaData _meta; private QueryResultCallback _callback; private boolean _declaredParams; // mainly a flag for now (null or not) /** * Construct a query for executing a Stored Procedure. * @param procedureName name of the database stored procedure. * @param meta * @param delegate the delegate which manages bind parameters on behalf of this */ public StoredProcedureQueryImpl(String procedureName, MultiQueryMetaData meta, QueryImpl delegate) { _name = procedureName; if (!isValidProcedureName(procedureName)) { throw new RuntimeException(procedureName + " is not a valid procedure name"); } _meta = meta; _delegate = delegate; _delegate.compile(); } /** * Gets the facade delegate that manages bind parameters on behalf of this receiver. * * @return */ public OpenJPAQuery getDelegate() { return _delegate; } /** * Gets the kernel delegate that is handles actual execution on behalf of this receiver. * * @return */ public org.apache.openjpa.kernel.Query getExecutableQuery() { return _delegate.getDelegate(); } private void buildParametersIfNeeded() { if (!_declaredParams) { for (MultiQueryMetaData.Parameter entry : _meta.getParameters()) { final Object key; final Parameter param; if (entry.getName() == null) { key = entry.getPosition(); param = new ParameterImpl(entry.getPosition(), entry.getType()); } else { key = entry.getName(); param = new ParameterImpl(entry.getName(), entry.getType()); } _delegate.declareParameter(key, param); } _declaredParams = true; } } /** * Executes this receiver by delegation to the underlying executable query. *
* This method is multi-call safe. The underlying executable query is executed * only for the first invocation. Subsequent */ @Override public boolean execute() { if (_callback == null) { _callback = (QueryResultCallback) getExecutableQuery().execute(_delegate.getParameterValues()); } return _callback.getExecutionResult(); } @Override public List getResultList() { execute(); try { Object list = _callback.callback(); RuntimeExceptionTranslator trans = PersistenceExceptions .getRollbackTranslator(_delegate.getEntityManager()); return new DelegatingResultList((ResultList) list, trans); } catch (Exception ex) { throw new javax.persistence.PersistenceException(ex); } } @Override public Object getSingleResult() { execute(); try { ResultList result = (ResultList) _callback.callback(); if (result == null || result.isEmpty()) throw new NoResultException(_loc.get("no-result", _name) .getMessage()); if (result.size() > 1) throw new NonUniqueResultException(_loc.get("non-unique-result", _name, result.size()).getMessage()); RuntimeExceptionTranslator trans = PersistenceExceptions .getRollbackTranslator(_delegate.getEntityManager()); return new DelegatingResultList(result, trans).iterator().next(); } catch (Exception ex) { throw new javax.persistence.PersistenceException(ex); } } @Override public boolean hasMoreResults() { return _callback != null && _callback.hasMoreResults(); } @Override public int getUpdateCount() { assertExecuted(); return _callback.getUpdateCount(); } @Override public int executeUpdate() { execute(); return _callback.getUpdateCount(); } @Override public Parameter getParameter(String name, Class type) { // TODO JPA 2.1 Method return _delegate.getParameter(name, type); } @Override public Parameter getParameter(int position, Class type) { // TODO JPA 2.1 Method return _delegate.getParameter(position, type); } @Override public boolean isBound(Parameter param) { // TODO JPA 2.1 Method return _delegate.isBound(param); } @Override public T getParameterValue(Parameter param) { // TODO JPA 2.1 Method return _delegate.getParameterValue(param); } @Override public T unwrap(Class cls) { // TODO JPA 2.1 Method return _delegate.unwrap(cls); } @Override public StoredProcedureQuery setParameter(Parameter param, T value) { buildParametersIfNeeded(); _delegate.setParameter(param, value); return this; } @Override public StoredProcedureQuery setParameter(Parameter param, Calendar cal, TemporalType temporalType) { buildParametersIfNeeded(); _delegate.setParameter(param, cal, temporalType); return this; } @Override public StoredProcedureQuery setParameter(Parameter param, Date value, TemporalType temporalType) { buildParametersIfNeeded(); _delegate.setParameter(param, value, temporalType); return this; } @Override public StoredProcedureQuery registerStoredProcedureParameter(int position, Class type, ParameterMode mode) { buildParametersIfNeeded(); ParameterImpl param = new ParameterImpl(position, type); _delegate.declareParameter(position, param); return this; } @Override public StoredProcedureQuery registerStoredProcedureParameter(String name, Class type, ParameterMode mode) { buildParametersIfNeeded(); ParameterImpl param = new ParameterImpl(name, type); _delegate.declareParameter(name, param); return this; } @Override public Object getOutputParameterValue(int position) { return _callback == null ? null : _callback.getOut(position); } @Override public Object getOutputParameterValue(String parameterName) { return _callback == null ? null : _callback.getOut(parameterName); } @Override public javax.persistence.Query setMaxResults(int maxResult) { // TODO JPA 2.1 Method return _delegate.setMaxResults(maxResult); } @Override public int getMaxResults() { // TODO JPA 2.1 Method return _delegate.getMaxResults(); } @Override public javax.persistence.Query setFirstResult(int startPosition) { // TODO JPA 2.1 Method return _delegate.setFirstResult(startPosition); } @Override public int getFirstResult() { // TODO JPA 2.1 Method return _delegate.getFirstResult(); } @Override public Map getHints() { // TODO JPA 2.1 Method return _delegate.getHints(); } @Override public Set> getParameters() { buildParametersIfNeeded(); return _delegate.getParameters(); } @Override public Parameter getParameter(String name) { buildParametersIfNeeded(); return _delegate.getParameter(name); } @Override public Parameter getParameter(int position) { buildParametersIfNeeded(); return _delegate.getParameter(position); } @Override public Object getParameterValue(String name) { buildParametersIfNeeded(); return _delegate.getParameterValue(name); } @Override public Object getParameterValue(int position) { buildParametersIfNeeded(); return _delegate.getParameter(position); } @Override public FlushModeType getFlushMode() { // TODO JPA 2.1 Method return _delegate.getFlushMode(); } @Override public javax.persistence.Query setLockMode(LockModeType lockMode) { // TODO JPA 2.1 Method return _delegate.setLockMode(lockMode); } @Override public LockModeType getLockMode() { // TODO JPA 2.1 Method return _delegate.getLockMode(); } @Override public StoredProcedureQuery setHint(String hintName, Object value) { _delegate.setHint(hintName, value); return this; } @Override public StoredProcedureQuery setParameter(String name, Object value) { buildParametersIfNeeded(); _delegate.setParameter(name, value); return this; } @Override public StoredProcedureQuery setParameter(String name, Calendar cal, TemporalType temporalType) { buildParametersIfNeeded(); _delegate.setParameter(name, cal, temporalType); return this; } @Override public StoredProcedureQuery setParameter(String name, Date date, TemporalType temporalType) { buildParametersIfNeeded(); _delegate.setParameter(name, date, temporalType); return this; } @Override public StoredProcedureQuery setParameter(int position, Object value) { buildParametersIfNeeded(); _delegate.setParameter(position, value); return this; } @Override public StoredProcedureQuery setParameter(int position, Calendar value, TemporalType temporalType) { buildParametersIfNeeded(); _delegate.setParameter(position, value, temporalType); return this; } @Override public StoredProcedureQuery setParameter(int position, Date value, TemporalType temporalType) { buildParametersIfNeeded(); _delegate.setParameter(position, value, temporalType); return this; } @Override public StoredProcedureQuery setFlushMode(FlushModeType flushMode) { // TODO JPA 2.1 Method _delegate.setFlushMode(flushMode); return this; } /** * Asserts that user has executed this query. */ void assertExecuted() { if (_callback == null) { throw new UserException(this + " has not been executed"); } } boolean isValidProcedureName(String s) { if (s == null || s.trim().length() == 0) { return false; } for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (ch == '#' || ch == '$' || Character.isJavaIdentifierPart(ch)) continue; return false; } return true; } @Override public String toString() { return _name; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy