We're updating the issue view to help you get more done. 

Hibernate throws SQLGrammarException: Error accessing table metadata when @Table is used with schema value and no catalog

Description

If an entity is annotated with @Table and the schema attribute is given a value but the catalog no AND the persistence.xml file does not fill in the hibernate.default_catalog, then this happens:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 22:31:55,009 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 84) MSC000001: Failed to start service jboss.persistenceunit."oberon.war#SSB": org.jboss.msc.service.StartException in service jboss.persistenceunit."oberon.war#SSB": javax.persistence.PersistenceException: [PersistenceUnit: SSB] Unable to build Hibernate SessionFactory at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:172) at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:117) at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:667) at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1.run(PersistenceUnitServiceImpl.java:182) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) at org.jboss.threads.JBossThread.run(JBossThread.java:320) Caused by: javax.persistence.PersistenceException: [PersistenceUnit: SSB] Unable to build Hibernate SessionFactory at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:954) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:882) at org.jboss.as.jpa.hibernate5.TwoPhaseBootstrapImpl.build(TwoPhaseBootstrapImpl.java:44) at org.jboss.as.jpa.service.PersistenceUnitServiceImpl$1$1.run(PersistenceUnitServiceImpl.java:154) ... 7 more Caused by: org.hibernate.exception.SQLGrammarException: Error accessing table metadata at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106) at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:109) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:95) at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.convertSQLException(InformationExtractorJdbcDatabaseMetaDataImpl.java:99) at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.locateTableInNamespace(InformationExtractorJdbcDatabaseMetaDataImpl.java:354) at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.getTable(InformationExtractorJdbcDatabaseMetaDataImpl.java:228) at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.getTableInformation(DatabaseInformationImpl.java:105) at org.hibernate.tool.schema.internal.SchemaValidatorImpl.doValidation(SchemaValidatorImpl.java:47) at org.hibernate.tool.hbm2ddl.SchemaValidator.validate(SchemaValidator.java:91) at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:473) at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:444) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879) ... 9 more Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: An object or column name is missing or empty. For SELECT INTO statements, verify each column has a name. For other statements, look for empty alias names. Aliases defined as "" or [] are not allowed. Change the alias to a valid name. at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:216) at com.microsoft.sqlserver.jdbc.TDSTokenHandler.onEOF(tdsparser.java:254) at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:84) at com.microsoft.sqlserver.jdbc.TDSParser.parse(tdsparser.java:39) at com.microsoft.sqlserver.jdbc.SQLServerConnection$1ConnectionCommand.doExecute(SQLServerConnection.java:1756) at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:5696) at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1715) at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectionCommand(SQLServerConnection.java:1761) at com.microsoft.sqlserver.jdbc.SQLServerConnection.setCatalog(SQLServerConnection.java:2063) at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.switchCatalogs(SQLServerDatabaseMetaData.java:326) at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getResultSetFromStoredProc(SQLServerDatabaseMetaData.java:277) at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getResultSetWithProvidedColumnNames(SQLServerDatabaseMetaData.java:304) at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getTables(SQLServerDatabaseMetaData.java:466) at org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl.locateTableInNamespace(InformationExtractorJdbcDatabaseMetaDataImpl.java:339) ... 16 more

From my investigations, SQL Server complains because Hibernate issues a query to get table metadata without specifying the database name

Looking in the code, in InformationExtractorJdbcDatabaseMetaDataImpl.java, the problem I think is at line 224:

1 2 3 4 5 6 7 public TableInformation getTable(Identifier catalog, Identifier schema, Identifier tableName) { if ( catalog != null || schema != null ) { // The table defined an explicit namespace. In such cases we only ever want to look // in the identified namespace return locateTableInNamespace( catalog, schema, tableName ); }

The code explicitly uses both catalog and schema from the table annotation even though only one might have been specified. (catalog != null

 

schema != null)

Shouldn't it fall back to the current namespace value for the one that is not specified? It doesn't make sense to force the user to specify the database name in persistence.xml or @Table just because the schema was specified. This wasn't required before (worked in 4.3)

Environment

Windows 7, Wildfly 10, Java 8

Status

Assignee

Chris Cranford

Reporter

Andrei Serea

Fix versions

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

5.2.2
5.1.0
5.0.10

Priority

Blocker