HHH-17424 - Have Dialect manage more of ExtractedDatabaseMetadata
https://hibernate.atlassian.net/browse/HHH-17424
This commit is contained in:
parent
fa5f0f75c2
commit
501b57a978
|
@ -275,8 +275,13 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
||||||
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
|
final ConfigurationService configurationService = serviceRegistry.getService( ConfigurationService.class );
|
||||||
final JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class );
|
final JdbcServices jdbcServices = serviceRegistry.getService( JdbcServices.class );
|
||||||
|
|
||||||
|
assert jdbcServices != null;
|
||||||
|
assert configurationService != null;
|
||||||
|
|
||||||
|
final Dialect dialect = jdbcServices.getJdbcEnvironment().getDialect();
|
||||||
|
|
||||||
final Map<String,Object> configurationSettings = new HashMap<>();
|
final Map<String,Object> configurationSettings = new HashMap<>();
|
||||||
configurationSettings.putAll( map( jdbcServices.getJdbcEnvironment().getDialect().getDefaultProperties() ) );
|
configurationSettings.putAll( map( dialect.getDefaultProperties() ) );
|
||||||
configurationSettings.putAll( configurationService.getSettings() );
|
configurationSettings.putAll( configurationService.getSettings() );
|
||||||
|
|
||||||
this.beanManagerReference = NullnessHelper.coalesceSuppliedValues(
|
this.beanManagerReference = NullnessHelper.coalesceSuppliedValues(
|
||||||
|
@ -488,7 +493,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.jdbcBatchSize = getInt( STATEMENT_BATCH_SIZE, configurationSettings, 1 );
|
this.jdbcBatchSize = getInt( STATEMENT_BATCH_SIZE, configurationSettings, 1 );
|
||||||
if ( !meta.supportsBatchUpdates() ) {
|
if ( disallowBatchUpdates( dialect, meta ) ) {
|
||||||
this.jdbcBatchSize = 0;
|
this.jdbcBatchSize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,6 +590,14 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean disallowBatchUpdates(Dialect dialect, ExtractedDatabaseMetaData meta) {
|
||||||
|
final Boolean dialectAnswer = dialect.supportsBatchUpdates();
|
||||||
|
if ( dialectAnswer != null ) {
|
||||||
|
return dialectAnswer;
|
||||||
|
}
|
||||||
|
return !meta.supportsBatchUpdates();
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private SqmMultiTableMutationStrategy resolveSqmMutationStrategy(
|
private SqmMultiTableMutationStrategy resolveSqmMutationStrategy(
|
||||||
String strategyName,
|
String strategyName,
|
||||||
|
|
|
@ -4952,6 +4952,30 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this Dialect support {@linkplain PreparedStatement#addBatch() batch updates}.
|
||||||
|
*
|
||||||
|
* @return {@code true} indicates it does; {@code false} indicates it does not; {@code null} indicates
|
||||||
|
* it might and that database-metadata should be consulted.
|
||||||
|
*
|
||||||
|
* @see org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData#supportsBatchUpdates
|
||||||
|
*/
|
||||||
|
public Boolean supportsBatchUpdates() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this Dialect support {@linkplain PreparedStatement#addBatch() batch updates}.
|
||||||
|
*
|
||||||
|
* @return {@code true} indicates it does; {@code false} indicates it does not; {@code null} indicates
|
||||||
|
* it might and that database-metadata should be consulted
|
||||||
|
*
|
||||||
|
* @see org.hibernate.engine.jdbc.env.spi.ExtractedDatabaseMetaData#supportsRefCursors
|
||||||
|
*/
|
||||||
|
public Boolean supportsRefCursors() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pluggable strategy for determining the {@link Size} to use for
|
* Pluggable strategy for determining the {@link Size} to use for
|
||||||
* columns of a given SQL type.
|
* columns of a given SQL type.
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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 http://www.gnu.org/licenses/lgpl-2.1.html.
|
||||||
|
*/
|
||||||
|
package org.hibernate.engine.jdbc.cursor.internal;
|
||||||
|
|
||||||
|
import java.sql.CallableStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class FallbackRefCursorSupport implements RefCursorSupport {
|
||||||
|
private final JdbcServices jdbcServices;
|
||||||
|
|
||||||
|
public FallbackRefCursorSupport(JdbcServices jdbcServices) {
|
||||||
|
this.jdbcServices = jdbcServices;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerRefCursorParameter(CallableStatement statement, int position) {
|
||||||
|
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) {
|
||||||
|
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) {
|
||||||
|
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) {
|
||||||
|
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 + "]"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.hibernate.boot.registry.StandardServiceInitiator;
|
import org.hibernate.boot.registry.StandardServiceInitiator;
|
||||||
import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport;
|
import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport;
|
||||||
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,7 +26,23 @@ public class RefCursorSupportInitiator implements StandardServiceInitiator<RefCu
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RefCursorSupport initiateService(Map<String, Object> configurationValues, ServiceRegistryImplementor registry) {
|
public RefCursorSupport initiateService(Map<String, Object> configurationValues, ServiceRegistryImplementor registry) {
|
||||||
return new StandardRefCursorSupport();
|
final JdbcServices jdbcServices = registry.getService( JdbcServices.class );
|
||||||
|
assert jdbcServices != null;
|
||||||
|
final boolean supportsRefCursors = useRefCursorSupport( jdbcServices );
|
||||||
|
if ( supportsRefCursors ) {
|
||||||
|
return new StandardRefCursorSupport( jdbcServices );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new FallbackRefCursorSupport( jdbcServices );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean useRefCursorSupport(JdbcServices jdbcServices) {
|
||||||
|
final Boolean dialectAnswer = jdbcServices.getDialect().supportsRefCursors();
|
||||||
|
if ( dialectAnswer != null ) {
|
||||||
|
return dialectAnswer;
|
||||||
|
}
|
||||||
|
return jdbcServices.getJdbcEnvironment().getExtractedDatabaseMetaData().supportsRefCursors();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,7 +15,6 @@ import java.sql.Types;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport;
|
import org.hibernate.engine.jdbc.cursor.spi.RefCursorSupport;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.service.spi.InjectService;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
@ -27,102 +26,49 @@ import org.jboss.logging.Logger;
|
||||||
public class StandardRefCursorSupport implements RefCursorSupport {
|
public class StandardRefCursorSupport implements RefCursorSupport {
|
||||||
private static final Logger log = Logger.getLogger( StandardRefCursorSupport.class );
|
private static final Logger log = Logger.getLogger( StandardRefCursorSupport.class );
|
||||||
|
|
||||||
private JdbcServices jdbcServices;
|
private final JdbcServices jdbcServices;
|
||||||
|
|
||||||
/**
|
public StandardRefCursorSupport(JdbcServices jdbcServices) {
|
||||||
* 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;
|
this.jdbcServices = jdbcServices;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerRefCursorParameter(CallableStatement statement, int position) {
|
public void registerRefCursorParameter(CallableStatement statement, int position) {
|
||||||
if ( jdbcServices.getExtractedMetaDataSupport().supportsRefCursors() ) {
|
try {
|
||||||
try {
|
statement.registerOutParameter( position, refCursorTypeCode() );
|
||||||
statement.registerOutParameter( position, refCursorTypeCode() );
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw jdbcServices.getSqlExceptionHelper().convert( e, "Error registering REF_CURSOR parameter [" + position + "]" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
catch (SQLException e) {
|
||||||
try {
|
throw jdbcServices.getSqlExceptionHelper().convert( e, "Error registering REF_CURSOR parameter [" + position + "]" );
|
||||||
jdbcServices.getDialect().registerResultSetOutParameter( statement, position );
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw jdbcServices.getSqlExceptionHelper().convert( e, "Error asking dialect to register ref cursor parameter [" + position + "]" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void registerRefCursorParameter(CallableStatement statement, String name) {
|
public void registerRefCursorParameter(CallableStatement statement, String name) {
|
||||||
if ( jdbcServices.getExtractedMetaDataSupport().supportsRefCursors() ) {
|
try {
|
||||||
try {
|
statement.registerOutParameter( name, refCursorTypeCode() );
|
||||||
statement.registerOutParameter( name, refCursorTypeCode() );
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw jdbcServices.getSqlExceptionHelper().convert( e, "Error registering REF_CURSOR parameter [" + name + "]" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
catch (SQLException e) {
|
||||||
try {
|
throw jdbcServices.getSqlExceptionHelper().convert( e, "Error registering REF_CURSOR parameter [" + name + "]" );
|
||||||
jdbcServices.getDialect().registerResultSetOutParameter( statement, name );
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw jdbcServices.getSqlExceptionHelper().convert( e, "Error asking dialect to register ref cursor parameter [" + name + "]" );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ResultSet getResultSet(CallableStatement statement, int position) {
|
public ResultSet getResultSet(CallableStatement statement, int position) {
|
||||||
if ( jdbcServices.getExtractedMetaDataSupport().supportsRefCursors() ) {
|
try {
|
||||||
try {
|
return statement.getObject( position, ResultSet.class );
|
||||||
return statement.getObject( position, ResultSet.class );
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new HibernateException( "Unexpected error extracting REF_CURSOR parameter [" + position + "]", e );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
catch (Exception e) {
|
||||||
try {
|
throw new HibernateException( "Unexpected error extracting REF_CURSOR parameter [" + position + "]", e );
|
||||||
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
|
@Override
|
||||||
public ResultSet getResultSet(CallableStatement statement, String name) {
|
public ResultSet getResultSet(CallableStatement statement, String name) {
|
||||||
if ( jdbcServices.getExtractedMetaDataSupport().supportsRefCursors() ) {
|
try {
|
||||||
try {
|
return statement.getObject( name, ResultSet.class );
|
||||||
return statement.getObject( name, ResultSet.class );
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new HibernateException( "Unexpected error extracting REF_CURSOR parameter [" + name + "]", e );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
catch (Exception e) {
|
||||||
try {
|
throw new HibernateException( "Unexpected error extracting REF_CURSOR parameter [" + name + "]", e );
|
||||||
return jdbcServices.getDialect().getResultSet( statement, name );
|
|
||||||
}
|
|
||||||
catch (SQLException e) {
|
|
||||||
throw jdbcServices.getSqlExceptionHelper().convert(
|
|
||||||
e,
|
|
||||||
"Error asking dialect to extract ResultSet from CallableStatement parameter [" + name + "]"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.engine.jdbc.env.spi;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
|
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,6 +31,8 @@ public interface ExtractedDatabaseMetaData {
|
||||||
* Retrieve the name of the catalog in effect when we connected to the database.
|
* Retrieve the name of the catalog in effect when we connected to the database.
|
||||||
*
|
*
|
||||||
* @return The catalog name
|
* @return The catalog name
|
||||||
|
*
|
||||||
|
* @see AvailableSettings#DEFAULT_SCHEMA
|
||||||
*/
|
*/
|
||||||
String getConnectionCatalogName();
|
String getConnectionCatalogName();
|
||||||
|
|
||||||
|
@ -45,14 +48,19 @@ public interface ExtractedDatabaseMetaData {
|
||||||
*
|
*
|
||||||
* @return {@code true} indicates the driver reported true; {@code false} indicates the driver reported false
|
* @return {@code true} indicates the driver reported true; {@code false} indicates the driver reported false
|
||||||
* or that the driver could not be asked.
|
* or that the driver could not be asked.
|
||||||
|
*
|
||||||
|
* @see AvailableSettings#CALLABLE_NAMED_PARAMS_ENABLED
|
||||||
*/
|
*/
|
||||||
boolean supportsNamedParameters();
|
boolean supportsNamedParameters();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does the driver report supporting REF_CURSORs?
|
* Does the driver report supporting {@link java.sql.Types#REF_CURSOR}?
|
||||||
*
|
*
|
||||||
* @return {@code true} indicates the driver reported true; {@code false} indicates the driver reported false
|
* @return {@code true} indicates the driver reported true; {@code false} indicates the driver reported false
|
||||||
* or that the driver could not be asked.
|
* or that the driver could not be asked.
|
||||||
|
*
|
||||||
|
* @see java.sql.DatabaseMetaData#supportsRefCursors()
|
||||||
|
* @see org.hibernate.dialect.Dialect#supportsRefCursors
|
||||||
*/
|
*/
|
||||||
boolean supportsRefCursors();
|
boolean supportsRefCursors();
|
||||||
|
|
||||||
|
@ -62,15 +70,17 @@ public interface ExtractedDatabaseMetaData {
|
||||||
* @return True if the driver reported to support {@link java.sql.ResultSet#TYPE_SCROLL_INSENSITIVE}.
|
* @return True if the driver reported to support {@link java.sql.ResultSet#TYPE_SCROLL_INSENSITIVE}.
|
||||||
*
|
*
|
||||||
* @see java.sql.DatabaseMetaData#supportsResultSetType
|
* @see java.sql.DatabaseMetaData#supportsResultSetType
|
||||||
|
* @see AvailableSettings#USE_SCROLLABLE_RESULTSET
|
||||||
*/
|
*/
|
||||||
boolean supportsScrollableResults();
|
boolean supportsScrollableResults();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Did the driver report to supporting retrieval of generated keys?
|
* Did the driver report to supporting retrieval of generated keys?
|
||||||
*
|
*
|
||||||
* @return True if the if the driver reported to support calls to {@link java.sql.Statement#getGeneratedKeys}
|
* @return True if the driver reported to support calls to {@link java.sql.Statement#getGeneratedKeys}
|
||||||
*
|
*
|
||||||
* @see java.sql.DatabaseMetaData#supportsGetGeneratedKeys
|
* @see java.sql.DatabaseMetaData#supportsGetGeneratedKeys
|
||||||
|
* @see AvailableSettings#USE_GET_GENERATED_KEYS
|
||||||
*/
|
*/
|
||||||
boolean supportsGetGeneratedKeys();
|
boolean supportsGetGeneratedKeys();
|
||||||
|
|
||||||
|
@ -80,6 +90,7 @@ public interface ExtractedDatabaseMetaData {
|
||||||
* @return True if the driver supports batched updates
|
* @return True if the driver supports batched updates
|
||||||
*
|
*
|
||||||
* @see java.sql.DatabaseMetaData#supportsBatchUpdates
|
* @see java.sql.DatabaseMetaData#supportsBatchUpdates
|
||||||
|
* @see org.hibernate.dialect.Dialect#supportsBatchUpdates
|
||||||
*/
|
*/
|
||||||
boolean supportsBatchUpdates();
|
boolean supportsBatchUpdates();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue