Home » Hibernate-3.3.2.GA » org.hibernate » engine » query » [javadoc | source]

    1   /*
    2    * Hibernate, Relational Persistence for Idiomatic Java
    3    *
    4    * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
    5    * indicated by the @author tags or express copyright attribution
    6    * statements applied by the authors.  All third-party contributions are
    7    * distributed under license by Red Hat Middleware LLC.
    8    *
    9    * This copyrighted material is made available to anyone wishing to use, modify,
   10    * copy, or redistribute it subject to the terms and conditions of the GNU
   11    * Lesser General Public License, as published by the Free Software Foundation.
   12    *
   13    * This program is distributed in the hope that it will be useful,
   14    * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   15    * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   16    * for more details.
   17    *
   18    * You should have received a copy of the GNU Lesser General Public License
   19    * along with this distribution; if not, write to:
   20    * Free Software Foundation, Inc.
   21    * 51 Franklin Street, Fifth Floor
   22    * Boston, MA  02110-1301  USA
   23    *
   24    */
   25   package org.hibernate.engine.query;
   26   
   27   import java.io.Serializable;
   28   import java.sql.PreparedStatement;
   29   import java.sql.SQLException;
   30   import java.util.Iterator;
   31   import java.util.List;
   32   import java.util.Map;
   33   
   34   import org.slf4j.Logger;
   35   import org.slf4j.LoggerFactory;
   36   import org.hibernate.HibernateException;
   37   import org.hibernate.QueryException;
   38   import org.hibernate.engine.query.sql.NativeSQLQuerySpecification;
   39   import org.hibernate.action.BulkOperationCleanupAction;
   40   import org.hibernate.engine.QueryParameters;
   41   import org.hibernate.engine.SessionFactoryImplementor;
   42   import org.hibernate.engine.SessionImplementor;
   43   import org.hibernate.engine.TypedValue;
   44   import org.hibernate.event.EventSource;
   45   import org.hibernate.exception.JDBCExceptionHelper;
   46   import org.hibernate.loader.custom.sql.SQLCustomQuery;
   47   import org.hibernate.type.Type;
   48   import org.hibernate.util.ArrayHelper;
   49   
   50   /**
   51    * Defines a query execution plan for a native-SQL query.
   52    * 
   53    * @author Steve Ebersole
   54    */
   55   public class NativeSQLQueryPlan implements Serializable {
   56   	private final String sourceQuery;
   57   
   58   	private final SQLCustomQuery customQuery;
   59   
   60   	private static final Logger log = LoggerFactory.getLogger(NativeSQLQueryPlan.class);
   61   
   62   	public NativeSQLQueryPlan(
   63   			NativeSQLQuerySpecification specification,
   64   			SessionFactoryImplementor factory) {
   65   		this.sourceQuery = specification.getQueryString();
   66   
   67   		customQuery = new SQLCustomQuery(
   68   				specification.getQueryString(),
   69   				specification.getQueryReturns(),
   70   				specification.getQuerySpaces(),
   71   				factory );
   72   	}
   73   
   74   	public String getSourceQuery() {
   75   		return sourceQuery;
   76   	}
   77   
   78   	public SQLCustomQuery getCustomQuery() {
   79   		return customQuery;
   80   	}
   81   
   82   	private int[] getNamedParameterLocs(String name) throws QueryException {
   83   		Object loc = customQuery.getNamedParameterBindPoints().get( name );
   84   		if ( loc == null ) {
   85   			throw new QueryException(
   86   					"Named parameter does not appear in Query: " + name,
   87   					customQuery.getSQL() );
   88   		}
   89   		if ( loc instanceof Integer ) {
   90   			return new int[] { ((Integer) loc ).intValue() };
   91   		}
   92   		else {
   93   			return ArrayHelper.toIntArray( (List) loc );
   94   		}
   95   	}
   96   
   97   	/**
   98   	 * Bind positional parameter values to the <tt>PreparedStatement</tt>
   99   	 * (these are parameters specified by a JDBC-style ?).
  100   	 */
  101   	private int bindPositionalParameters(final PreparedStatement st,
  102   			final QueryParameters queryParameters, final int start,
  103   			final SessionImplementor session) throws SQLException,
  104   			HibernateException {
  105   
  106   		final Object[] values = queryParameters
  107   				.getFilteredPositionalParameterValues();
  108   		final Type[] types = queryParameters
  109   				.getFilteredPositionalParameterTypes();
  110   		int span = 0;
  111   		for (int i = 0; i < values.length; i++) {
  112   			types[i].nullSafeSet( st, values[i], start + span, session );
  113   			span += types[i].getColumnSpan( session.getFactory() );
  114   		}
  115   		return span;
  116   	}
  117   
  118   	/**
  119   	 * Bind named parameters to the <tt>PreparedStatement</tt>. This has an
  120   	 * empty implementation on this superclass and should be implemented by
  121   	 * subclasses (queries) which allow named parameters.
  122   	 */
  123   	private int bindNamedParameters(final PreparedStatement ps,
  124   			final Map namedParams, final int start,
  125   			final SessionImplementor session) throws SQLException,
  126   			HibernateException {
  127   
  128   		if ( namedParams != null ) {
  129   			// assumes that types are all of span 1
  130   			Iterator iter = namedParams.entrySet().iterator();
  131   			int result = 0;
  132   			while ( iter.hasNext() ) {
  133   				Map.Entry e = (Map.Entry) iter.next();
  134   				String name = (String) e.getKey();
  135   				TypedValue typedval = (TypedValue) e.getValue();
  136   				int[] locs = getNamedParameterLocs( name );
  137   				for (int i = 0; i < locs.length; i++) {
  138   					if ( log.isDebugEnabled() ) {
  139   						log.debug( "bindNamedParameters() "
  140   								+ typedval.getValue() + " -> " + name + " ["
  141   								+ (locs[i] + start ) + "]" );
  142   					}
  143   					typedval.getType().nullSafeSet( ps, typedval.getValue(),
  144   							locs[i] + start, session );
  145   				}
  146   				result += locs.length;
  147   			}
  148   			return result;
  149   		}
  150   		else {
  151   			return 0;
  152   		}
  153   	}
  154   
  155   	protected void coordinateSharedCacheCleanup(SessionImplementor session) {
  156   		BulkOperationCleanupAction action = new BulkOperationCleanupAction( session, getCustomQuery().getQuerySpaces() );
  157   
  158   		action.init();
  159   
  160   		if ( session.isEventSource() ) {
  161   			( ( EventSource ) session ).getActionQueue().addAction( action );
  162   		}
  163   	}
  164   
  165   	public int performExecuteUpdate(QueryParameters queryParameters,
  166   			SessionImplementor session) throws HibernateException {
  167   		
  168   		coordinateSharedCacheCleanup( session );
  169   		
  170   		if(queryParameters.isCallable()) {
  171   			throw new IllegalArgumentException("callable not yet supported for native queries");
  172   		}
  173   		
  174   		int result = 0;
  175   		PreparedStatement ps;
  176   		try {
  177   			queryParameters.processFilters( this.customQuery.getSQL(),
  178   					session );
  179   			String sql = queryParameters.getFilteredSQL();
  180   
  181   			ps = session.getBatcher().prepareStatement( sql );
  182   
  183   			try {
  184   				int col = 1;
  185   				col += bindPositionalParameters( ps, queryParameters, col,
  186   						session );
  187   				col += bindNamedParameters( ps, queryParameters
  188   						.getNamedParameters(), col, session );
  189   				result = ps.executeUpdate();
  190   			}
  191   			finally {
  192   				if ( ps != null ) {
  193   					session.getBatcher().closeStatement( ps );
  194   				}				
  195   			}			
  196   		}
  197   		catch (SQLException sqle) {
  198   			throw JDBCExceptionHelper.convert( session.getFactory()
  199   					.getSQLExceptionConverter(), sqle,
  200   					"could not execute native bulk manipulation query", this.sourceQuery );
  201   		}
  202   
  203   		return result;
  204   	}
  205   	
  206   }

Home » Hibernate-3.3.2.GA » org.hibernate » engine » query » [javadoc | source]