Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.internal.CoreLogging;
import org.hibernate.loader.custom.CustomLoader;
import org.hibernate.loader.custom.CustomQuery;
import org.hibernate.loader.custom.sql.SQLQueryReturnProcessor;
import org.hibernate.loader.spi.AfterLoadAction;
import org.hibernate.result.NoMoreReturnsException;
import org.hibernate.result.Output;
import org.hibernate.result.Outputs;
import org.hibernate.result.spi.ResultContext;
import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
*/
public class OutputsImpl implements Outputs {
private static final Logger log = CoreLogging.logger( OutputsImpl.class );
private final ResultContext context;
private final PreparedStatement jdbcStatement;
private final CustomLoaderExtension loader;
private CurrentReturnState currentReturnState;
public OutputsImpl(ResultContext context, PreparedStatement jdbcStatement) {
this.context = context;
this.jdbcStatement = jdbcStatement;
// For now... but see the LoadPlan work; eventually this should just be a ResultSetProcessor.
this.loader = buildSpecializedCustomLoader( context );
try {
final boolean isResultSet = jdbcStatement.execute();
currentReturnState = buildCurrentReturnState( isResultSet );
}
catch (SQLException e) {
throw convert( e, "Error calling CallableStatement.getMoreResults" );
}
}
private CurrentReturnState buildCurrentReturnState(boolean isResultSet) {
int updateCount = -1;
if ( ! isResultSet ) {
try {
updateCount = jdbcStatement.getUpdateCount();
}
catch (SQLException e) {
throw convert( e, "Error calling CallableStatement.getUpdateCount" );
}
}
return buildCurrentReturnState( isResultSet, updateCount );
}
protected CurrentReturnState buildCurrentReturnState(boolean isResultSet, int updateCount) {
return new CurrentReturnState( isResultSet, updateCount );
}
protected JDBCException convert(SQLException e, String message) {
return context.getSession().getFactory().getSQLExceptionHelper().convert(
e,
message,
context.getSql()
);
}
@Override
public Output getCurrent() {
if ( currentReturnState == null ) {
return null;
}
return currentReturnState.getOutput();
}
@Override
public boolean goToNext() {
if ( currentReturnState == null ) {
return false;
}
if ( currentReturnState.indicatesMoreOutputs() )
// prepare the next return state
try {
final boolean isResultSet = jdbcStatement.getMoreResults();
currentReturnState = buildCurrentReturnState( isResultSet );
}
catch (SQLException e) {
throw convert( e, "Error calling CallableStatement.getMoreResults" );
}
// and return
return currentReturnState != null && currentReturnState.indicatesMoreOutputs();
}
@Override
public void release() {
try {
jdbcStatement.close();
}
catch (SQLException e) {
log.debug( "Unable to close PreparedStatement", e );
}
}
private List extractCurrentResults() {
try {
return extractResults( jdbcStatement.getResultSet() );
}
catch (SQLException e) {
throw convert( e, "Error calling CallableStatement.getResultSet" );
}
}
protected List extractResults(ResultSet resultSet) {
try {
return loader.processResultSet( resultSet );
}
catch (SQLException e) {
throw convert( e, "Error extracting results from CallableStatement" );
}
}
/**
* Encapsulates the information needed to interpret the current return within a result
*/
protected class CurrentReturnState {
private final boolean isResultSet;
private final int updateCount;
private Output rtn;
protected CurrentReturnState(boolean isResultSet, int updateCount) {
this.isResultSet = isResultSet;
this.updateCount = updateCount;
}
public boolean indicatesMoreOutputs() {
return isResultSet() || getUpdateCount() >= 0;
}
public boolean isResultSet() {
return isResultSet;
}
public int getUpdateCount() {
return updateCount;
}
public Output getOutput() {
if ( rtn == null ) {
rtn = buildOutput();
}
return rtn;
}
protected Output buildOutput() {
if ( log.isDebugEnabled() ) {
log.debugf(
"Building Return [isResultSet=%s, updateCount=%s, extendedReturn=%s",
isResultSet(),
getUpdateCount(),
hasExtendedReturns()
);
}
if ( isResultSet() ) {
return buildResultSetOutput( extractCurrentResults() );
}
else if ( getUpdateCount() >= 0 ) {
return buildUpdateCountOutput( updateCount );
}
else if ( hasExtendedReturns() ) {
return buildExtendedReturn();
}
throw new NoMoreReturnsException();
}
// hooks for stored procedure (out param) processing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
protected Output buildResultSetOutput(List list) {
return new ResultSetOutputImpl( list );
}
protected Output buildUpdateCountOutput(int updateCount) {
return new UpdateCountOutputImpl( updateCount );
}
protected boolean hasExtendedReturns() {
return false;
}
protected Output buildExtendedReturn() {
throw new IllegalStateException( "State does not define extended returns" );
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Hooks into Hibernate's Loader hierarchy for ResultSet -> Object mapping
private static CustomLoaderExtension buildSpecializedCustomLoader(final ResultContext context) {
// might be better to just manually construct the Return(s).. SQLQueryReturnProcessor does a lot of
// work that is really unnecessary here.
final SQLQueryReturnProcessor processor = new SQLQueryReturnProcessor(
context.getQueryReturns(),
context.getSession().getFactory()
);
processor.process();
final List customReturns = processor.generateCustomReturns( false );
CustomQuery customQuery = new CustomQuery() {
@Override
public String getSQL() {
return context.getSql();
}
@Override
public Set getQuerySpaces() {
return context.getSynchronizedQuerySpaces();
}
@Override
public Map getNamedParameterBindPoints() {
// no named parameters in terms of embedded in the SQL string
return null;
}
@Override
public List getCustomQueryReturns() {
return customReturns;
}
};
return new CustomLoaderExtension(
customQuery,
context.getQueryParameters(),
context.getSession()
);
}
private static class CustomLoaderExtension extends CustomLoader {
private QueryParameters queryParameters;
private SessionImplementor session;
private boolean needsDiscovery = true;
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 {
if ( needsDiscovery ) {
super.autoDiscoverTypes( resultSet );
// todo : EntityAliases discovery
needsDiscovery = false;
}
return super.processResultSet(
resultSet,
queryParameters,
session,
true,
null,
Integer.MAX_VALUE,
Collections.emptyList()
);
}
}
}