Skip to content

Commit 2eaa094

Browse files
committed
HHH-19063 - Drop forms of SchemaNameResolver performing reflection
1 parent b1cb1b7 commit 2eaa094

File tree

23 files changed

+576
-667
lines changed

23 files changed

+576
-667
lines changed

hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import org.hibernate.DuplicateMappingException;
1414
import org.hibernate.HibernateException;
1515
import org.hibernate.MappingException;
16-
import org.hibernate.SessionFactory;
1716
import org.hibernate.annotations.CollectionTypeRegistration;
1817
import org.hibernate.annotations.Imported;
1918
import org.hibernate.annotations.Parameter;
@@ -345,7 +344,7 @@ public SessionFactoryBuilder getSessionFactoryBuilder() {
345344
}
346345

347346
@Override
348-
public SessionFactory buildSessionFactory() {
347+
public SessionFactoryImplementor buildSessionFactory() {
349348
throw new UnsupportedOperationException(
350349
"You should not be building a SessionFactory from an in-flight metadata collector; and of course " +
351350
"we should better segment this in the API :)"

hibernate-core/src/main/java/org/hibernate/boot/internal/MetadataImpl.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
import org.hibernate.HibernateException;
1919
import org.hibernate.MappingException;
20-
import org.hibernate.SessionFactory;
2120
import org.hibernate.boot.SessionFactoryBuilder;
2221
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
2322
import org.hibernate.boot.model.NamedEntityGraphDefinition;
@@ -205,8 +204,8 @@ private ClassLoaderService getClassLoaderService() {
205204
}
206205

207206
@Override
208-
public SessionFactory buildSessionFactory() {
209-
return getSessionFactoryBuilder().build();
207+
public SessionFactoryImplementor buildSessionFactory() {
208+
return (SessionFactoryImplementor) getSessionFactoryBuilder().build();
210209
}
211210

212211
@Override

hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingMetadata.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,7 @@
44
*/
55
package org.hibernate.boot.spi;
66

7-
import java.util.Collection;
8-
import java.util.Map;
9-
import java.util.Set;
10-
import java.util.UUID;
11-
import java.util.function.Consumer;
12-
import java.util.function.Supplier;
13-
147
import org.hibernate.MappingException;
15-
import org.hibernate.SessionFactory;
168
import org.hibernate.boot.SessionFactoryBuilder;
179
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
1810
import org.hibernate.boot.model.NamedEntityGraphDefinition;
@@ -36,6 +28,13 @@
3628
import org.hibernate.type.Type;
3729
import org.hibernate.type.spi.TypeConfiguration;
3830

31+
import java.util.Collection;
32+
import java.util.Map;
33+
import java.util.Set;
34+
import java.util.UUID;
35+
import java.util.function.Consumer;
36+
import java.util.function.Supplier;
37+
3938
/**
4039
* Convenience base class for custom implementors of {@link MetadataImplementor} using delegation.
4140
*
@@ -75,7 +74,7 @@ public SessionFactoryBuilder getSessionFactoryBuilder() {
7574
}
7675

7776
@Override
78-
public SessionFactory buildSessionFactory() {
77+
public SessionFactoryImplementor buildSessionFactory() {
7978
return delegate.buildSessionFactory();
8079
}
8180

hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataImplementor.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,7 @@ public interface MetadataImplementor extends Metadata {
6060
Component getGenericComponent(Class<?> componentClass);
6161

6262
DiscriminatorType<?> resolveEmbeddableDiscriminatorType(Class<?> embeddableClass, Supplier<DiscriminatorType<?>> supplier);
63+
64+
@Override
65+
SessionFactoryImplementor buildSessionFactory();
6366
}

hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3653,7 +3653,12 @@ public String[] getDropSchemaCommand(String schemaName) {
36533653
* make use of the Java 1.7 {@link Connection#getSchema()} method.
36543654
*
36553655
* @return The current schema retrieval SQL
3656+
*
3657+
* @deprecated Since Hibernate now baselines on Java 17,
3658+
* {@link Connection#getSchema()} is always available directly.
3659+
* Never used internally.
36563660
*/
3661+
@Deprecated
36573662
public String getCurrentSchemaCommand() {
36583663
return null;
36593664
}

hibernate-core/src/main/java/org/hibernate/dialect/SybaseDialect.java

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,8 @@
44
*/
55
package org.hibernate.dialect;
66

7-
import java.sql.DatabaseMetaData;
8-
import java.sql.SQLException;
9-
import java.sql.Types;
10-
import java.time.temporal.TemporalAccessor;
11-
import java.util.Calendar;
12-
import java.util.Date;
13-
import java.util.TimeZone;
14-
7+
import jakarta.persistence.TemporalType;
8+
import org.hibernate.HibernateException;
159
import org.hibernate.boot.model.FunctionContributions;
1610
import org.hibernate.boot.model.TypeContributions;
1711
import org.hibernate.dialect.function.CommonFunctionFactory;
@@ -24,20 +18,22 @@
2418
import org.hibernate.dialect.unique.SkipNullableUniqueDelegate;
2519
import org.hibernate.dialect.unique.UniqueDelegate;
2620
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
21+
import org.hibernate.engine.jdbc.env.internal.DefaultSchemaNameResolver;
2722
import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy;
2823
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
2924
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
3025
import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
26+
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
3127
import org.hibernate.engine.spi.LoadQueryInfluencers;
3228
import org.hibernate.engine.spi.SessionFactoryImplementor;
3329
import org.hibernate.procedure.internal.JTDSCallableStatementSupport;
3430
import org.hibernate.procedure.internal.SybaseCallableStatementSupport;
3531
import org.hibernate.procedure.spi.CallableStatementSupport;
32+
import org.hibernate.query.common.TemporalUnit;
3633
import org.hibernate.query.spi.QueryOptions;
3734
import org.hibernate.query.spi.QueryParameterBindings;
3835
import org.hibernate.query.sqm.CastType;
3936
import org.hibernate.query.sqm.IntervalType;
40-
import org.hibernate.query.common.TemporalUnit;
4137
import org.hibernate.query.sqm.internal.DomainParameterXref;
4238
import org.hibernate.query.sqm.sql.SqmTranslator;
4339
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
@@ -63,7 +59,15 @@
6359
import org.hibernate.type.descriptor.jdbc.TinyIntAsSmallIntJdbcType;
6460
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
6561

66-
import jakarta.persistence.TemporalType;
62+
import java.sql.Connection;
63+
import java.sql.DatabaseMetaData;
64+
import java.sql.ResultSet;
65+
import java.sql.SQLException;
66+
import java.sql.Types;
67+
import java.time.temporal.TemporalAccessor;
68+
import java.util.Calendar;
69+
import java.util.Date;
70+
import java.util.TimeZone;
6771

6872
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsDate;
6973
import static org.hibernate.type.descriptor.DateTimeUtils.appendAsLocalTime;
@@ -91,6 +95,8 @@ public class SybaseDialect extends AbstractTransactSQLDialect {
9195
@Deprecated(forRemoval = true)
9296
protected final boolean jtdsDriver;
9397

98+
private final SchemaNameResolver schemaNameResolver;
99+
94100
public SybaseDialect() {
95101
this( MINIMUM_VERSION );
96102
}
@@ -99,12 +105,22 @@ public SybaseDialect(DatabaseVersion version) {
99105
super(version);
100106
this.driverKind = SybaseDriverKind.OTHER;
101107
this.jtdsDriver = true;
108+
this.schemaNameResolver = determineSchemaNameResolver( driverKind );
109+
}
110+
111+
private static SchemaNameResolver determineSchemaNameResolver(SybaseDriverKind driverKind) {
112+
// if the driver is jTDS, then we need to use a query to determine the schema name.
113+
// if we don't know the driver (OTHER), then be safe and use the query approach
114+
return driverKind != SybaseDriverKind.JCONNECT
115+
? new JTDSSchemaNameResolver()
116+
: DefaultSchemaNameResolver.INSTANCE;
102117
}
103118

104119
public SybaseDialect(DialectResolutionInfo info) {
105120
super(info);
106121
this.driverKind = SybaseDriverKind.determineKind( info );
107122
this.jtdsDriver = driverKind == SybaseDriverKind.JTDS;
123+
this.schemaNameResolver = determineSchemaNameResolver( driverKind );
108124
}
109125

110126
@Override
@@ -321,6 +337,11 @@ public boolean canCreateSchema() {
321337
return false;
322338
}
323339

340+
@Override
341+
public SchemaNameResolver getSchemaNameResolver() {
342+
return schemaNameResolver;
343+
}
344+
324345
@Override
325346
public String getCurrentSchemaCommand() {
326347
return "select user_name()";
@@ -556,4 +577,26 @@ public boolean supportsRowValueConstructorSyntaxInInList() {
556577
return false;
557578
}
558579

580+
private static class JTDSSchemaNameResolver implements SchemaNameResolver {
581+
@Override
582+
public String resolveSchemaName(Connection connection, Dialect dialect) throws SQLException {
583+
//noinspection deprecation
584+
final String command = dialect.getCurrentSchemaCommand();
585+
if ( command == null ) {
586+
throw new HibernateException(
587+
"Use of DefaultSchemaNameResolver requires Dialect to provide the " +
588+
"proper SQL statement/command but provided Dialect [" +
589+
dialect.getClass().getName() + "] did not return anything " +
590+
"from Dialect#getCurrentSchemaCommand"
591+
);
592+
}
593+
594+
try (final java.sql.Statement statement = connection.createStatement()) {
595+
try (ResultSet resultSet = statement.executeQuery( command )) {
596+
return resultSet.next() ? resultSet.getString( 1 ) : null;
597+
}
598+
}
599+
}
600+
}
601+
559602
}

hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/DefaultSchemaNameResolver.java

Lines changed: 5 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -4,108 +4,27 @@
44
*/
55
package org.hibernate.engine.jdbc.env.internal;
66

7-
import java.lang.reflect.Method;
8-
import java.sql.Connection;
9-
import java.sql.ResultSet;
10-
import java.sql.SQLException;
11-
import java.sql.Statement;
12-
13-
import org.hibernate.HibernateException;
147
import org.hibernate.dialect.Dialect;
158
import org.hibernate.engine.jdbc.env.spi.SchemaNameResolver;
169

17-
import org.jboss.logging.Logger;
10+
import java.sql.Connection;
11+
import java.sql.SQLException;
1812

1913
/**
20-
* Default implementation of {@link SchemaNameResolver}.
14+
* Default implementation of {@link SchemaNameResolver}
15+
* using {@link Connection#getSchema()}.
2116
*
2217
* @author Steve Ebersole
2318
*/
2419
public class DefaultSchemaNameResolver implements SchemaNameResolver {
25-
private static final Logger log = Logger.getLogger( DefaultSchemaNameResolver.class );
26-
2720
public static final DefaultSchemaNameResolver INSTANCE = new DefaultSchemaNameResolver();
2821

29-
// NOTE: The actual delegate should not be cached in DefaultSchemaNameResolver because,
30-
// in the case of multiple data sources, there may be a data source that
31-
// requires a different delegate. See HHH-12392.
32-
3322
private DefaultSchemaNameResolver() {
3423
}
3524

36-
private SchemaNameResolver determineAppropriateResolverDelegate(Connection connection) {
37-
// unfortunately Connection#getSchema is only available in Java 1.7 and above
38-
// and Hibernate still baselines on 1.6. So for now, use reflection and
39-
// leverage the Connection#getSchema method if it is available.
40-
try {
41-
final Class<? extends Connection> jdbcConnectionClass = connection.getClass();
42-
final Method getSchemaMethod = jdbcConnectionClass.getMethod( "getSchema" );
43-
if ( getSchemaMethod.getReturnType().equals( String.class ) ) {
44-
try {
45-
// If the JDBC driver does not implement the Java 7 spec, but the JRE is Java 7
46-
// then the getSchemaMethod is not null but the call to getSchema() throws an java.lang.AbstractMethodError
47-
connection.getSchema();
48-
return new SchemaNameResolverJava17Delegate();
49-
}
50-
catch (AbstractMethodError e) {
51-
log.debugf( "Unable to use Java 1.7 Connection#getSchema" );
52-
return SchemaNameResolverFallbackDelegate.INSTANCE;
53-
}
54-
}
55-
else {
56-
log.debugf( "Unable to use Java 1.7 Connection#getSchema" );
57-
return SchemaNameResolverFallbackDelegate.INSTANCE;
58-
}
59-
}
60-
catch (Exception e) {
61-
log.debugf(
62-
"Unable to use Java 1.7 Connection#getSchema : An error occurred trying to resolve the connection default schema resolver: %s",
63-
e.getMessage() );
64-
return SchemaNameResolverFallbackDelegate.INSTANCE;
65-
}
66-
}
67-
6825
@Override
6926
public String resolveSchemaName(Connection connection, Dialect dialect) throws SQLException {
70-
// NOTE: delegate should not be cached in DefaultSchemaNameResolver because,
71-
// in the case of multiple data sources, there may be a data source that
72-
// requires a different delegate. See HHH-12392.
73-
final SchemaNameResolver delegate = determineAppropriateResolverDelegate( connection );
74-
return delegate.resolveSchemaName( connection, dialect );
75-
}
76-
77-
public static class SchemaNameResolverJava17Delegate implements SchemaNameResolver {
78-
79-
@Override
80-
public String resolveSchemaName(Connection connection, Dialect dialect) throws SQLException {
81-
return connection.getSchema();
82-
}
27+
return connection.getSchema();
8328
}
8429

85-
public static class SchemaNameResolverFallbackDelegate implements SchemaNameResolver {
86-
/**
87-
* Singleton access
88-
*/
89-
public static final SchemaNameResolverFallbackDelegate INSTANCE = new SchemaNameResolverFallbackDelegate();
90-
91-
@Override
92-
public String resolveSchemaName(Connection connection, Dialect dialect) throws SQLException {
93-
final String command = dialect.getCurrentSchemaCommand();
94-
if ( command == null ) {
95-
throw new HibernateException(
96-
"Use of DefaultSchemaNameResolver requires Dialect to provide the " +
97-
"proper SQL statement/command but provided Dialect [" +
98-
dialect.getClass().getName() + "] did not return anything " +
99-
"from Dialect#getCurrentSchemaCommand"
100-
);
101-
}
102-
103-
try (
104-
final Statement statement = connection.createStatement();
105-
final ResultSet resultSet = statement.executeQuery( dialect.getCurrentSchemaCommand() )
106-
) {
107-
return resultSet.next() ? resultSet.getString( 1 ) : null;
108-
}
109-
}
110-
}
11130
}

hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/JdbcEnvironment.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,20 @@ public interface JdbcEnvironment extends Service {
3535
ExtractedDatabaseMetaData getExtractedDatabaseMetaData();
3636

3737
/**
38-
* Get the current database catalog. Typically will come from either {@link java.sql.Connection#getCatalog()}
39-
* or {@value org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
38+
* Get the current database catalog. Typically, will come from either
39+
* {@link java.sql.Connection#getCatalog()} or
40+
* {@value org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
4041
*
4142
* @return The current catalog.
4243
*/
4344
Identifier getCurrentCatalog();
4445

4546
/**
46-
* Get the current database catalog. Typically will come from either
47-
* {@link SchemaNameResolver#resolveSchemaName(java.sql.Connection, Dialect)} or
48-
* {@value org.hibernate.cfg.AvailableSettings#DEFAULT_CATALOG}.
47+
* Get the current database catalog. Typically, will come from either
48+
* {@link java.sql.Connection#getSchema()} or
49+
* {@value org.hibernate.cfg.AvailableSettings#DEFAULT_SCHEMA}.
50+
*
51+
* @see org.hibernate.engine.jdbc.env.spi.SchemaNameResolver
4952
*
5053
* @return The current schema
5154
*/

hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/SchemaNameResolver.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
/**
1313
* Contract for resolving the schema of a {@link Connection}.
1414
*
15+
* @apiNote Exists mainly for historical reasons when Hibernate
16+
* baselines on Java versions before 8 when {@linkplain Connection#getSchema()}
17+
* was introduced. We still use it at the moment because some drivers do not
18+
* implement it (jTDS) and/or some databases do not support schemas and
19+
* their drivers don't DoTheRightThing.
20+
*
1521
* @author Steve Ebersole
1622
*/
1723
public interface SchemaNameResolver {
@@ -21,7 +27,7 @@ public interface SchemaNameResolver {
2127
* @param connection The JDBC connection
2228
* @param dialect The {@link Dialect}
2329
*
24-
* @return The name of the schema (may be null).
30+
* @return The name of the schema; may be null.
2531
*/
2632
String resolveSchemaName(Connection connection, Dialect dialect) throws SQLException;
2733
}

0 commit comments

Comments
 (0)