Package org.hibernate.result.internal

Source Code of org.hibernate.result.internal.ResultImpl$UpdateCountReturn

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.  All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA  02110-1301  USA
*/
package org.hibernate.result.internal;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.JDBCException;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.loader.custom.CustomLoader;
import org.hibernate.loader.custom.CustomQuery;
import org.hibernate.loader.custom.sql.SQLQueryReturnProcessor;
import org.hibernate.result.NoMoreReturnsException;
import org.hibernate.result.Result;
import org.hibernate.result.Return;
import org.hibernate.result.spi.ResultContext;

/**
* @author Steve Ebersole
*/
public class ResultImpl implements Result {
  private final ResultContext context;
  private final PreparedStatement jdbcStatement;
  private final CustomLoaderExtension loader;

  private CurrentReturnDescriptor currentReturnDescriptor;

  private boolean executed = false;

  public ResultImpl(ResultContext context, PreparedStatement jdbcStatement) {
    this.context = context;
    this.jdbcStatement = jdbcStatement;

    // For now...
    this.loader = buildSpecializedCustomLoader( context );
  }

  @Override
  public boolean hasMoreReturns() {
    if ( currentReturnDescriptor == null ) {
      final boolean isResultSet;

      if ( executed ) {
        try {
          isResultSet = jdbcStatement.getMoreResults();
        }
        catch (SQLException e) {
          throw convert( e, "Error calling CallableStatement.getMoreResults" );
        }
      }
      else {
        try {
          isResultSet = jdbcStatement.execute();
        }
        catch (SQLException e) {
          throw convert( e, "Error calling CallableStatement.execute" );
        }
        executed = true;
      }

      int updateCount = -1;
      if ( ! isResultSet ) {
        try {
          updateCount = jdbcStatement.getUpdateCount();
        }
        catch (SQLException e) {
          throw convert( e, "Error calling CallableStatement.getUpdateCount" );
        }
      }

      currentReturnDescriptor = buildCurrentReturnDescriptor( isResultSet, updateCount );
    }

    return hasMoreReturns( currentReturnDescriptor );
  }

  protected CurrentReturnDescriptor buildCurrentReturnDescriptor(boolean isResultSet, int updateCount) {
    return new CurrentReturnDescriptor( isResultSet, updateCount );
  }

  protected boolean hasMoreReturns(CurrentReturnDescriptor descriptor) {
    return descriptor.isResultSet
        || descriptor.updateCount >= 0;
  }

  @Override
  public Return getNextReturn() {
    if ( currentReturnDescriptor == null ) {
      if ( executed ) {
        throw new IllegalStateException( "Unexpected condition" );
      }
      else {
        throw new IllegalStateException( "hasMoreReturns() not called before getNextReturn()" );
      }
    }

    if ( ! hasMoreReturns( currentReturnDescriptor ) ) {
      throw new NoMoreReturnsException( "Results have been exhausted" );
    }

    CurrentReturnDescriptor copyReturnDescriptor = currentReturnDescriptor;
    currentReturnDescriptor = null;

    if ( copyReturnDescriptor.isResultSet ) {
      try {
        return new ResultSetReturn( this, jdbcStatement.getResultSet() );
      }
      catch (SQLException e) {
        throw convert( e, "Error calling CallableStatement.getResultSet" );
      }
    }
    else if ( copyReturnDescriptor.updateCount >= 0 ) {
      return new UpdateCountReturn( this, copyReturnDescriptor.updateCount );
    }
    else {
      return buildExtendedReturn( copyReturnDescriptor );
    }
  }

  protected Return buildExtendedReturn(CurrentReturnDescriptor copyReturnDescriptor) {
    throw new NoMoreReturnsException( "Results have been exhausted" );
  }

  protected JDBCException convert(SQLException e, String message) {
    return context.getSession().getFactory().getSQLExceptionHelper().convert(
        e,
        message,
        context.getSql()
    );
  }

  protected static class CurrentReturnDescriptor {
    private final boolean isResultSet;
    private final int updateCount;

    protected CurrentReturnDescriptor(boolean isResultSet, int updateCount) {
      this.isResultSet = isResultSet;
      this.updateCount = updateCount;
    }
  }

  protected static class ResultSetReturn implements org.hibernate.result.ResultSetReturn {
    private final ResultImpl storedProcedureOutputs;
    private final ResultSet resultSet;

    public ResultSetReturn(ResultImpl storedProcedureOutputs, ResultSet resultSet) {
      this.storedProcedureOutputs = storedProcedureOutputs;
      this.resultSet = resultSet;
    }

    @Override
    public boolean isResultSet() {
      return true;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List getResultList() {
      try {
        return storedProcedureOutputs.loader.processResultSet( resultSet );
      }
      catch (SQLException e) {
        throw storedProcedureOutputs.convert( e, "Error calling ResultSet.next" );
      }
    }

    @Override
    public Object getSingleResult() {
      List results = getResultList();
      if ( results == null || results.isEmpty() ) {
        return null;
      }
      else {
        return results.get( 0 );
      }
    }
  }

  protected static class UpdateCountReturn implements org.hibernate.result.UpdateCountReturn {
    private final ResultImpl result;
    private final int updateCount;

    public UpdateCountReturn(ResultImpl result, int updateCount) {
      this.result = result;
      this.updateCount = updateCount;
    }

    @Override
    public int getUpdateCount() {
      return updateCount;
    }

    @Override
    public boolean isResultSet() {
      return false;
    }
  }

  private static CustomLoaderExtension buildSpecializedCustomLoader(final ResultContext context) {
    final SQLQueryReturnProcessor processor = new SQLQueryReturnProcessor(
        context.getQueryReturns(),
        context.getSession().getFactory()
    );
    processor.process();
    final List<org.hibernate.loader.custom.Return> customReturns = processor.generateCustomReturns( false );

    CustomQuery customQuery = new CustomQuery() {
      @Override
      public String getSQL() {
        return context.getSql();
      }

      @Override
      public Set<String> getQuerySpaces() {
        return context.getSynchronizedQuerySpaces();
      }

      @Override
      public Map getNamedParameterBindPoints() {
        // no named parameters in terms of embedded in the SQL string
        return null;
      }

      @Override
      public List<org.hibernate.loader.custom.Return> getCustomQueryReturns() {
        return customReturns;
      }
    };

    return new CustomLoaderExtension(
        customQuery,
        context.getQueryParameters(),
        context.getSession()
    );
  }

  private static class CustomLoaderExtension extends CustomLoader {
    private QueryParameters queryParameters;
    private SessionImplementor session;

    public CustomLoaderExtension(
        CustomQuery customQuery,
        QueryParameters queryParameters,
        SessionImplementor session) {
      super( customQuery, session.getFactory() );
      this.queryParameters = queryParameters;
      this.session = session;
    }

    // todo : this would be a great way to add locking to stored procedure support (at least where returning entities).

    public List processResultSet(ResultSet resultSet) throws SQLException {
      super.autoDiscoverTypes( resultSet );
      return super.processResultSet(
          resultSet,
          queryParameters,
          session,
          true,
          null,
          Integer.MAX_VALUE,
          Collections.<AfterLoadAction>emptyList()
      );
    }
  }
}
TOP

Related Classes of org.hibernate.result.internal.ResultImpl$UpdateCountReturn

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.