Uploaded image for project: 'Hibernate ORM'
  1. HHH-10978

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

    Details

    • Bug Testcase Reminder (view):

      Bug reports should generally be accompanied by a test case!

    • Last commented by a user?:
      true
    • Sprint:

      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:

      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:

      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)

        Attachments

          Activity

            People

            • Votes:
              10 Vote for this issue
              Watchers:
              9 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: