diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ColumnNameCache.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ColumnNameCache.java deleted file mode 100644 index c960ed57e2..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ColumnNameCache.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.engine.jdbc; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Cache of column-name -> column-index resolutions - * - * @author Steve Ebersole - */ -public final class ColumnNameCache { - private static final float LOAD_FACTOR = .75f; - - private final ConcurrentHashMap columnNameToIndexCache; - - /** - * Constructs a ColumnNameCache - * - * @param columnCount The number of columns to be cached. - */ - public ColumnNameCache(int columnCount) { - // should *not* need to grow beyond the size of the total number of columns in the rs - this.columnNameToIndexCache = new ConcurrentHashMap<>( - columnCount + (int)( columnCount * LOAD_FACTOR ) + 1, - LOAD_FACTOR - ); - } - - /** - * Resolve the column name/alias to its index - * - * @param columnName The name/alias of the column - * @param rs The ResultSet - * - * @return The index - * - * @throws SQLException INdicates a problems accessing the underlying JDBC ResultSet - */ - public Integer getIndexForColumnName(String columnName, ResultSet rs) throws SQLException { - final Integer cached = columnNameToIndexCache.get( columnName ); - if ( cached != null ) { - return cached; - } - else { - final Integer index = Integer.valueOf( rs.findColumn( columnName ) ); - columnNameToIndexCache.put( columnName, index); - return index; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ResultSetWrapperProxy.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ResultSetWrapperProxy.java deleted file mode 100644 index d179c0af9c..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ResultSetWrapperProxy.java +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.engine.jdbc; - -import static org.hibernate.internal.CoreLogging.messageLogger; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.service.ServiceRegistry; - -/** - * A proxy for a ResultSet delegate, responsible for locally caching the columnName-to-columnIndex resolution that - * has been found to be inefficient in a few vendor's drivers (i.e., Oracle and Postgres). - * - * @author Steve Ebersole - * @author Gail Badner - */ -public class ResultSetWrapperProxy implements InvocationHandler { - private static final CoreMessageLogger LOG = messageLogger( ResultSetWrapperProxy.class ); - - private static final SqlExceptionHelper SQL_EXCEPTION_HELPER = new SqlExceptionHelper( false ); - - private static final Map NAME_TO_INDEX_METHOD_MAPPING; - - private final ResultSet rs; - private final ColumnNameCache columnNameCache; - - static { - Map nameToIndexMethodMapping = new HashMap<>(); - for ( Method method : ResultSet.class.getDeclaredMethods() ) { - if ( isFirstArgColumnLabel( method ) ) { - try { - nameToIndexMethodMapping.put( - new ResultSetMethodKey( method.getName(), method.getParameterTypes() ), - locateCorrespondingColumnIndexMethod( method ) - ); - } - catch (NoSuchMethodException e) { - LOG.unableToSwitchToMethodUsingColumnIndex( method ); - } - } - } - NAME_TO_INDEX_METHOD_MAPPING = Collections.unmodifiableMap( nameToIndexMethodMapping ); - } - - private ResultSetWrapperProxy(ResultSet rs, ColumnNameCache columnNameCache) { - this.rs = rs; - this.columnNameCache = columnNameCache; - } - - /** - * Generates a proxy wrapping the ResultSet. - * - * @param resultSet The resultSet to wrap. - * @param columnNameCache The cache storing data for converting column names to column indexes. - * @param serviceRegistry Access to any needed services - * - * @return The generated proxy. - */ - public static ResultSet generateProxy( - ResultSet resultSet, - ColumnNameCache columnNameCache, - ServiceRegistry serviceRegistry) { - return serviceRegistry.getService( ClassLoaderService.class ).generateProxy( - new ResultSetWrapperProxy( resultSet, columnNameCache ), - ResultSet.class - ); - } - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - if ( "findColumn".equals( method.getName() ) ) { - return findColumn( (String) args[0] ); - } - - if ( isFirstArgColumnLabel( method ) ) { - Method columnIndexMethod = NAME_TO_INDEX_METHOD_MAPPING.get( new ResultSetMethodKey( method.getName(), method.getParameterTypes() ) ); - if ( columnIndexMethod != null ) { - try { - final Integer columnIndex = findColumn( (String) args[0] ); - - return invokeMethod( columnIndexMethod, buildColumnIndexMethodArgs( args, columnIndex ) ); - } - catch ( SQLException ex ) { - final String msg = "Exception getting column index for column: [" + args[0] + - "].\nReverting to using: [" + args[0] + - "] as first argument for method: [" + method + "]"; - SQL_EXCEPTION_HELPER.logExceptions( ex, msg ); - } - } - } - - return invokeMethod( method, args ); - } - - /** - * Locate the column index corresponding to the given column name via the cache. - * - * @param columnName The column name to resolve into an index. - * @return The column index corresponding to the given column name. - * @throws SQLException if the ResultSet object does not contain columnName or a database access error occurs - */ - private Integer findColumn(String columnName) throws SQLException { - return columnNameCache.getIndexForColumnName( columnName, rs ); - } - - private static boolean isFirstArgColumnLabel(Method method) { - // method name should start with either get or update - if ( ! ( method.getName().startsWith( "get" ) || method.getName().startsWith( "update" ) ) ) { - return false; - } - - // method should have at least one parameter - if ( ! ( method.getParameterCount() > 0 ) ) { - return false; - } - - // The first parameter should be a String (the column name) - if ( ! method.getParameterTypes()[0].equals( String.class ) ) { - return false; - } - - return true; - } - - /** - * For a given {@link ResultSet} method passed a column name, locate the corresponding method passed the same - * parameters but the column index. - * - * @param columnNameMethod The method passed the column name - * @return The corresponding method passed the column index. - * @throws NoSuchMethodException Should never happen, but... - */ - private static Method locateCorrespondingColumnIndexMethod(Method columnNameMethod) throws NoSuchMethodException { - final Class[] actualParameterTypes = new Class[columnNameMethod.getParameterCount()]; - actualParameterTypes[0] = int.class; - System.arraycopy( - columnNameMethod.getParameterTypes(), - 1, - actualParameterTypes, - 1, - columnNameMethod.getParameterCount() - 1 - ); - return columnNameMethod.getDeclaringClass().getMethod( columnNameMethod.getName(), actualParameterTypes ); - } - - private Object[] buildColumnIndexMethodArgs(Object[] incomingArgs, Integer columnIndex) { - final Object[] actualArgs = new Object[incomingArgs.length]; - actualArgs[0] = columnIndex; - System.arraycopy( incomingArgs, 1, actualArgs, 1, incomingArgs.length - 1 ); - return actualArgs; - } - - private Object invokeMethod(Method method, Object[] args) throws Throwable { - try { - return method.invoke( rs, args ); - } - catch ( InvocationTargetException e ) { - throw e.getTargetException(); - } - } - - private static class ResultSetMethodKey { - - private String methodName; - - private Class[] parameterTypes; - - public ResultSetMethodKey(String methodName, Class[] parameterTypes) { - this.methodName = methodName; - this.parameterTypes = parameterTypes; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + methodName.hashCode(); - result = prime * result + Arrays.hashCode( parameterTypes ); - return result; - } - - @Override - public boolean equals(Object obj) { - if ( this == obj ) { - return true; - } - if ( obj == null ) { - return false; - } - if ( getClass() != obj.getClass() ) { - return false; - } - - ResultSetMethodKey other = (ResultSetMethodKey) obj; - if ( !methodName.equals( other.methodName ) ) { - return false; - } - if ( !Arrays.equals( parameterTypes, other.parameterTypes ) ) { - return false; - } - return true; - } - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java index d9fef62108..d7b9f1b6ce 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/JdbcServicesImpl.java @@ -18,7 +18,6 @@ import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator; import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.jdbc.spi.JdbcServices; -import org.hibernate.engine.jdbc.spi.ResultSetWrapper; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlStatementLogger; import org.hibernate.internal.util.config.ConfigurationHelper; @@ -39,8 +38,6 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi private SqlStatementLogger sqlStatementLogger; - private ResultSetWrapperImpl resultSetWrapper; - @Override public void injectServices(ServiceRegistryImplementor serviceRegistry) { this.serviceRegistry = serviceRegistry; @@ -59,8 +56,6 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi final long logSlowQuery = ConfigurationHelper.getLong( Environment.LOG_SLOW_QUERY, configValues, 0 ); this.sqlStatementLogger = new SqlStatementLogger( showSQL, formatSQL, highlightSQL, logSlowQuery ); - - resultSetWrapper = new ResultSetWrapperImpl( serviceRegistry ); } @Override @@ -110,8 +105,4 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi return null; } - @Override - public ResultSetWrapper getResultSetWrapper() { - return resultSetWrapper; - } } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/ResultSetWrapperImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/ResultSetWrapperImpl.java deleted file mode 100644 index f9eb248785..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/internal/ResultSetWrapperImpl.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.engine.jdbc.internal; - -import java.sql.ResultSet; - -import org.hibernate.engine.jdbc.ColumnNameCache; -import org.hibernate.engine.jdbc.ResultSetWrapperProxy; -import org.hibernate.engine.jdbc.spi.ResultSetWrapper; -import org.hibernate.service.ServiceRegistry; - -/** - * Standard Hibernate implementation for wrapping a {@link ResultSet} in a - " column name cache" wrapper. - * - * @author Steve Ebersole - * @author Gail Badner - */ -public class ResultSetWrapperImpl implements ResultSetWrapper { - private final ServiceRegistry serviceRegistry; - - public ResultSetWrapperImpl(ServiceRegistry serviceRegistry) { - this.serviceRegistry = serviceRegistry; - } - - @Override - public ResultSet wrap(ResultSet resultSet, ColumnNameCache columnNameCache) { - return ResultSetWrapperProxy.generateProxy( resultSet, columnNameCache, serviceRegistry ); - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcServices.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcServices.java index e2b8f2671f..4f8f2aa267 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcServices.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/JdbcServices.java @@ -74,12 +74,6 @@ public interface JdbcServices extends Service { */ LobCreator getLobCreator(LobCreationContext lobCreationContext); - /** - * Obtain service for wrapping a {@link java.sql.ResultSet} in a "column name cache" wrapper. - * @return The ResultSet wrapper. - */ - ResultSetWrapper getResultSetWrapper(); - /** * Access the executor for {@link org.hibernate.sql.exec.spi.JdbcSelect} operations */ diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ResultSetWrapper.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ResultSetWrapper.java deleted file mode 100644 index 355bbc7857..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/ResultSetWrapper.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.engine.jdbc.spi; - -import java.sql.ResultSet; - -import org.hibernate.engine.jdbc.ColumnNameCache; - -/** - * Contract for wrapping a {@link ResultSet} in a "column name cache" wrapper. - * - * @author Gail Badner - */ -public interface ResultSetWrapper { - /** - * Wrap a result set in a "column name cache" wrapper. - * - * @param resultSet The result set to wrap - * @param columnNameCache The column name cache. - * - * @return The wrapped result set. - */ - public ResultSet wrap(ResultSet resultSet, ColumnNameCache columnNameCache); -} diff --git a/hibernate-core/src/test/java/org/hibernate/engine/jdbc/ResultSetWrapperProxyTest.java b/hibernate-core/src/test/java/org/hibernate/engine/jdbc/ResultSetWrapperProxyTest.java deleted file mode 100644 index bee91c98dc..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/engine/jdbc/ResultSetWrapperProxyTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * License: GNU Lesser General Public License (LGPL), version 2.1 or later. - * See the lgpl.txt file in the root directory or . - */ -package org.hibernate.engine.jdbc; - -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.service.ServiceRegistry; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mockito; - -public class ResultSetWrapperProxyTest { - - private ResultSet resultSet; - - private ResultSet resultSetProxy; - - @Before - public void initialize() throws SQLException { - ServiceRegistry serviceRegistry = Mockito.mock( ServiceRegistry.class ); - when( serviceRegistry.getService( eq( ClassLoaderService.class ) ) ).thenReturn( new ClassLoaderServiceImpl() ); - - ColumnNameCache columnNameCache = new ColumnNameCache( 2 ); - - resultSet = Mockito.mock( ResultSet.class ); - when( resultSet.findColumn( eq( "myColumn" ) ) ).thenReturn( 1 ); - - resultSetProxy = ResultSetWrapperProxy.generateProxy( resultSet, columnNameCache, serviceRegistry ); - } - - @Test - public void testRedirectedGetMethod() throws SQLException { - resultSetProxy.getBigDecimal( "myColumn" ); - - verify( resultSet, times( 1 ) ).getBigDecimal( 1 ); - } - - @SuppressWarnings("deprecation") - @Test - public void testRedirectedGetMethodWithAdditionalParameters() throws SQLException { - resultSetProxy.getBigDecimal( "myColumn", 8 ); - - verify( resultSet, times( 1 ) ).getBigDecimal( 1, 8 ); - } - - @Test - public void testRedirectedUpdateMethod() throws SQLException { - resultSetProxy.updateInt( "myColumn", 19 ); - - verify( resultSet, times( 1 ) ).updateInt( 1, 19 ); - } - - @SuppressWarnings("deprecation") - @Test - public void testIntMethods() throws SQLException { - resultSetProxy.getBigDecimal( 3 ); - verify( resultSet, times( 1 ) ).getBigDecimal( 3 ); - - resultSetProxy.getBigDecimal( 13, 8 ); - verify( resultSet, times( 1 ) ).getBigDecimal( 13, 8 ); - - resultSetProxy.updateInt( 23, 19 ); - verify( resultSet, times( 1 ) ).updateInt( 23, 19 ); - } - - @Test - public void testStandardMethod() throws SQLException { - resultSetProxy.getFetchSize(); - - verify( resultSet, times( 1 ) ).getFetchSize(); - } -} diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/boot/BasicTestingJdbcServiceImpl.java b/hibernate-testing/src/main/java/org/hibernate/testing/boot/BasicTestingJdbcServiceImpl.java index 836c3f50c8..fa15f812bf 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/boot/BasicTestingJdbcServiceImpl.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/boot/BasicTestingJdbcServiceImpl.java @@ -17,9 +17,7 @@ import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess; import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl; import org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; -import org.hibernate.engine.jdbc.internal.ResultSetWrapperImpl; import org.hibernate.engine.jdbc.spi.JdbcServices; -import org.hibernate.engine.jdbc.spi.ResultSetWrapper; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlStatementLogger; import org.hibernate.service.ServiceRegistry; @@ -98,10 +96,6 @@ public class BasicTestingJdbcServiceImpl implements JdbcServices, ServiceRegistr return jdbcEnvironment.getLobCreatorBuilder().buildLobCreator( lobCreationContext ); } - public ResultSetWrapper getResultSetWrapper() { - return new ResultSetWrapperImpl( serviceRegistry ); - } - public SqlStatementLogger getSqlStatementLogger() { return sqlStatementLogger; }