Home » hibernate-entitymanager-3.3.2.GA » org.hibernate » engine » query » [javadoc | source]
    1   package org.hibernate.engine.query;
    2   
    3   import java.io.Serializable;
    4   import java.sql.Connection;
    5   import java.sql.PreparedStatement;
    6   import java.sql.SQLException;
    7   import java.util.Iterator;
    8   import java.util.List;
    9   import java.util.Map;
   10   
   11   import org.apache.commons.logging.Log;
   12   import org.apache.commons.logging.LogFactory;
   13   import org.hibernate.HibernateException;
   14   import org.hibernate.QueryException;
   15   import org.hibernate.action.BulkOperationCleanupAction;
   16   import org.hibernate.engine.QueryParameters;
   17   import org.hibernate.engine.SessionFactoryImplementor;
   18   import org.hibernate.engine.SessionImplementor;
   19   import org.hibernate.engine.TypedValue;
   20   import org.hibernate.event.EventSource;
   21   import org.hibernate.exception.JDBCExceptionHelper;
   22   import org.hibernate.loader.custom.SQLCustomQuery;
   23   import org.hibernate.pretty.Formatter;
   24   import org.hibernate.type.Type;
   25   import org.hibernate.util.ArrayHelper;
   26   
   27   /**
   28    * Defines a query execution plan for a native-SQL query.
   29    * 
   30    * @author <a href="mailto:steve@hibernate.org">Steve Ebersole </a>
   31    */
   32   public class NativeSQLQueryPlan implements Serializable {
   33   	private final String sourceQuery;
   34   
   35   	private final SQLCustomQuery customQuery;
   36   
   37   	private static final Log log = LogFactory.getLog(NativeSQLQueryPlan.class);
   38   
   39   	public NativeSQLQueryPlan(NativeSQLQuerySpecification specification,
   40   			SessionFactoryImplementor factory) {
   41   		this.sourceQuery = specification.getQueryString();
   42   
   43   		customQuery = new SQLCustomQuery( specification.getSqlQueryReturns(),
   44   				specification.getSqlQueryScalarReturns(), specification
   45   						.getQueryString(), specification.getQuerySpaces(),
   46   				factory );
   47   	}
   48   
   49   	public String getSourceQuery() {
   50   		return sourceQuery;
   51   	}
   52   
   53   	public SQLCustomQuery getCustomQuery() {
   54   		return customQuery;
   55   	}
   56   
   57   	private int[] getNamedParameterLocs(String name) throws QueryException {
   58   		Object loc = customQuery.getNamedParameterBindPoints().get( name );
   59   		if ( loc == null ) {
   60   			throw new QueryException(
   61   					"Named parameter does not appear in Query: " + name,
   62   					customQuery.getSQL() );
   63   		}
   64   		if ( loc instanceof Integer ) {
   65   			return new int[] { ((Integer) loc ).intValue() };
   66   		}
   67   		else {
   68   			return ArrayHelper.toIntArray( (List) loc );
   69   		}
   70   	}
   71   
   72   	/**
   73   	 * Bind positional parameter values to the <tt>PreparedStatement</tt>
   74   	 * (these are parameters specified by a JDBC-style ?).
   75   	 */
   76   	private int bindPositionalParameters(final PreparedStatement st,
   77   			final QueryParameters queryParameters, final int start,
   78   			final SessionImplementor session) throws SQLException,
   79   			HibernateException {
   80   
   81   		final Object[] values = queryParameters
   82   				.getFilteredPositionalParameterValues();
   83   		final Type[] types = queryParameters
   84   				.getFilteredPositionalParameterTypes();
   85   		int span = 0;
   86   		for (int i = 0; i < values.length; i++) {
   87   			types[i].nullSafeSet( st, values[i], start + span, session );
   88   			span += types[i].getColumnSpan( session.getFactory() );
   89   		}
   90   		return span;
   91   	}
   92   
   93   	/**
   94   	 * Bind named parameters to the <tt>PreparedStatement</tt>. This has an
   95   	 * empty implementation on this superclass and should be implemented by
   96   	 * subclasses (queries) which allow named parameters.
   97   	 */
   98   	private int bindNamedParameters(final PreparedStatement ps,
   99   			final Map namedParams, final int start,
  100   			final SessionImplementor session) throws SQLException,
  101   			HibernateException {
  102   
  103   		if ( namedParams != null ) {
  104   			// assumes that types are all of span 1
  105   			Iterator iter = namedParams.entrySet().iterator();
  106   			int result = 0;
  107   			while ( iter.hasNext() ) {
  108   				Map.Entry e = (Map.Entry) iter.next();
  109   				String name = (String) e.getKey();
  110   				TypedValue typedval = (TypedValue) e.getValue();
  111   				int[] locs = getNamedParameterLocs( name );
  112   				for (int i = 0; i < locs.length; i++) {
  113   					if ( log.isDebugEnabled() ) {
  114   						log.debug( "bindNamedParameters() "
  115   								+ typedval.getValue() + " -> " + name + " ["
  116   								+ (locs[i] + start ) + "]" );
  117   					}
  118   					typedval.getType().nullSafeSet( ps, typedval.getValue(),
  119   							locs[i] + start, session );
  120   				}
  121   				result += locs.length;
  122   			}
  123   			return result;
  124   		}
  125   		else {
  126   			return 0;
  127   		}
  128   	}
  129   
  130   	protected void coordinateSharedCacheCleanup(SessionImplementor session) {
  131   		BulkOperationCleanupAction action = new BulkOperationCleanupAction( session, getCustomQuery().getQuerySpaces() );
  132   
  133   		action.init();
  134   
  135   		if ( session.isEventSource() ) {
  136   			( ( EventSource ) session ).getActionQueue().addAction( action );
  137   		}
  138   	}
  139   
  140   	public int performExecuteUpdate(QueryParameters queryParameters,
  141   			SessionImplementor session) throws HibernateException {
  142   		
  143   		coordinateSharedCacheCleanup( session );
  144   		
  145   		if(queryParameters.isCallable()) {
  146   			throw new IllegalArgumentException("callable not yet supported for native queries");
  147   		}
  148   		
  149   		int result = 0;
  150   		PreparedStatement ps = null;
  151   		try {
  152   			queryParameters.processFilters( this.customQuery.getSQL(),
  153   					session );
  154   			String sql = queryParameters.getFilteredSQL();
  155   
  156   			ps = session.getBatcher().prepareStatement( sql );
  157   
  158   			try {
  159   				int col = 1;
  160   				col += bindPositionalParameters( ps, queryParameters, col,
  161   						session );
  162   				col += bindNamedParameters( ps, queryParameters
  163   						.getNamedParameters(), col, session );
  164   				result = ps.executeUpdate();
  165   			}
  166   			finally {
  167   				if ( ps != null ) {
  168   					session.getBatcher().closeStatement( ps );
  169   				}				
  170   			}			
  171   		}
  172   		catch (SQLException sqle) {
  173   			throw JDBCExceptionHelper.convert( session.getFactory()
  174   					.getSQLExceptionConverter(), sqle,
  175   					"could not execute native bulk manipulation query", this.sourceQuery );
  176   		}
  177   
  178   		return result;
  179   	}
  180   	
  181   }

Save This Page
Home » hibernate-entitymanager-3.3.2.GA » org.hibernate » engine » query » [javadoc | source]