/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2012, 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.engine.jdbc.cursor.internal;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.CallableStatement;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.HibernateException;
import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.service.spi.InjectService;

import org.jboss.logging.Logger;

Standard implementation of RefCursorSupport
Author:Steve Ebersole
/** * Standard implementation of RefCursorSupport * * @author Steve Ebersole */
public class StandardRefCursorSupport implements RefCursorSupport { private static final Logger log = Logger.getLogger( StandardRefCursorSupport.class ); private JdbcServices jdbcServices;
Hook for service registry to be able to inject JdbcServices
Params:
  • jdbcServices – The JdbcServices service
/** * Hook for service registry to be able to inject JdbcServices * * @param jdbcServices The JdbcServices service */
@InjectService @SuppressWarnings("UnusedDeclaration") public void injectJdbcServices(JdbcServices jdbcServices) { this.jdbcServices = jdbcServices; } @Override public void registerRefCursorParameter(CallableStatement statement, int position) { if ( jdbcServices.getExtractedMetaDataSupport().supportsRefCursors() ) { try { statement.registerOutParameter( position, refCursorTypeCode() ); } catch (SQLException e) { throw jdbcServices.getSqlExceptionHelper().convert( e, "Error registering REF_CURSOR parameter [" + position + "]" ); } } else { try { jdbcServices.getDialect().registerResultSetOutParameter( statement, position ); } catch (SQLException e) { throw jdbcServices.getSqlExceptionHelper().convert( e, "Error asking dialect to register ref cursor parameter [" + position + "]" ); } } } @Override public void registerRefCursorParameter(CallableStatement statement, String name) { if ( jdbcServices.getExtractedMetaDataSupport().supportsRefCursors() ) { try { statement.registerOutParameter( name, refCursorTypeCode() ); } catch (SQLException e) { throw jdbcServices.getSqlExceptionHelper().convert( e, "Error registering REF_CURSOR parameter [" + name + "]" ); } } else { try { jdbcServices.getDialect().registerResultSetOutParameter( statement, name ); } catch (SQLException e) { throw jdbcServices.getSqlExceptionHelper().convert( e, "Error asking dialect to register ref cursor parameter [" + name + "]" ); } } } @Override public ResultSet getResultSet(CallableStatement statement, int position) { if ( jdbcServices.getExtractedMetaDataSupport().supportsRefCursors() ) { try { return (ResultSet) getResultSetByPositionMethod().invoke( statement, position, ResultSet.class ); } catch (InvocationTargetException e) { if ( e.getTargetException() instanceof SQLException ) { throw jdbcServices.getSqlExceptionHelper().convert( (SQLException) e.getTargetException(), "Error extracting REF_CURSOR parameter [" + position + "]" ); } else { throw new HibernateException( "Unexpected error extracting REF_CURSOR parameter [" + position + "]", e.getTargetException() ); } } catch (Exception e) { throw new HibernateException( "Unexpected error extracting REF_CURSOR parameter [" + position + "]", e ); } } else { try { return jdbcServices.getDialect().getResultSet( statement, position ); } catch (SQLException e) { throw jdbcServices.getSqlExceptionHelper().convert( e, "Error asking dialect to extract ResultSet from CallableStatement parameter [" + position + "]" ); } } } @Override public ResultSet getResultSet(CallableStatement statement, String name) { if ( jdbcServices.getExtractedMetaDataSupport().supportsRefCursors() ) { try { return (ResultSet) getResultSetByNameMethod().invoke( statement, name, ResultSet.class ); } catch (InvocationTargetException e) { if ( e.getTargetException() instanceof SQLException ) { throw jdbcServices.getSqlExceptionHelper().convert( (SQLException) e.getTargetException(), "Error extracting REF_CURSOR parameter [" + name + "]" ); } else { throw new HibernateException( "Unexpected error extracting REF_CURSOR parameter [" + name + "]", e.getTargetException() ); } } catch (Exception e) { throw new HibernateException( "Unexpected error extracting REF_CURSOR parameter [" + name + "]", e ); } } else { try { return jdbcServices.getDialect().getResultSet( statement, name ); } catch (SQLException e) { throw jdbcServices.getSqlExceptionHelper().convert( e, "Error asking dialect to extract ResultSet from CallableStatement parameter [" + name + "]" ); } } }
Does this JDBC metadata indicate that the driver defines REF_CURSOR support?
Params:
  • meta – The JDBC metadata
Returns:true if the metadata indicates that the driver defines REF_CURSOR support
/** * Does this JDBC metadata indicate that the driver defines REF_CURSOR support? * * @param meta The JDBC metadata * * @return {@code true} if the metadata indicates that the driver defines REF_CURSOR support */
public static boolean supportsRefCursors(DatabaseMetaData meta) { // Standard JDBC REF_CURSOR support was not added until Java 8, so we need to use reflection to attempt to // access these fields/methods... try { return (Boolean) meta.getClass().getMethod( "supportsRefCursors" ).invoke( null ); } catch (NoSuchMethodException e) { log.trace( "JDBC DatabaseMetaData class does not define supportsRefCursors method..." ); } catch (Exception e) { log.debug( "Unexpected error trying to gauge level of JDBC REF_CURSOR support : " + e.getMessage() ); } return false; } private static Integer refCursorTypeCode; private int refCursorTypeCode() { if ( refCursorTypeCode == null ) { try { refCursorTypeCode = (Integer) Types.class.getField( "REF_CURSOR" ).get( null ); } catch (NoSuchFieldException e) { throw new HibernateException( "java.sql.Types class does not define REF_CURSOR field..." ); } catch (IllegalAccessException e) { throw new HibernateException( "Unexpected error trying to determine REF_CURSOR field value : " + e.getMessage() ); } } return refCursorTypeCode; } private static Method getResultSetByPositionMethod; private Method getResultSetByPositionMethod() { if ( getResultSetByPositionMethod == null ) { try { getResultSetByPositionMethod = CallableStatement.class.getMethod( "getObject", int.class, Class.class ); } catch (NoSuchMethodException e) { throw new HibernateException( "CallableStatement class does not define getObject(int,Class) method" ); } catch (Exception e) { throw new HibernateException( "Unexpected error trying to access CallableStatement#getObject(int,Class)" ); } } return getResultSetByPositionMethod; } private static Method getResultSetByNameMethod; private Method getResultSetByNameMethod() { if ( getResultSetByNameMethod == null ) { try { getResultSetByNameMethod = CallableStatement.class.getMethod( "getObject", String.class, Class.class ); } catch (NoSuchMethodException e) { throw new HibernateException( "CallableStatement class does not define getObject(String,Class) method" ); } catch (Exception e) { throw new HibernateException( "Unexpected error trying to access CallableStatement#getObject(String,Class)" ); } } return getResultSetByNameMethod; } }