Changeset 7391


Ignore:
Timestamp:
Jun 9, 2017, 8:56:56 AM (5 years ago)
Author:
Nicklas Nordborg
Message:

References #2084: Upgrade to Hibernate 5.2

Implemented a workaround for the unquoted table name problem. It is a bit of a "hack" that involves replacing a private and final variable inside a Hibernate class with our own implementation that forces names to be quoted. We do this only when doing a database schema update and revert to the original value afterwards.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/core/net/sf/basedb/core/hibernate/SchemaGenerator.java

    r7381 r7391  
    2222package net.sf.basedb.core.hibernate;
    2323
     24import java.lang.reflect.Field;
    2425import java.sql.Connection;
    2526import java.sql.SQLException;
     
    3738
    3839import org.hibernate.boot.Metadata;
     40import org.hibernate.boot.model.naming.Identifier;
     41import org.hibernate.boot.model.relational.QualifiedName;
     42import org.hibernate.boot.model.relational.QualifiedSequenceName;
     43import org.hibernate.boot.model.relational.QualifiedTableName;
    3944import org.hibernate.boot.spi.MetadataImplementor;
    4045import org.hibernate.dialect.Dialect;
     46import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl;
     47import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
     48import org.hibernate.engine.jdbc.env.spi.QualifiedObjectNameFormatter;
    4149import org.hibernate.jdbc.Work;
    4250import org.hibernate.service.ServiceRegistry;
     
    120128   
    121129    Statement stmt = connection.createStatement();
     130    String currentSql = null;
     131    ForceQuotedTableNameFormatter tableNameFormatter = new ForceQuotedTableNameFormatter(metadata);
    122132    try
    123133    {
     
    132142      {
    133143        log.info("Generating schema update script");
     144        tableNameFormatter.applyWorkaroundForHibernateBug();
    134145        SchemaMigrator schemaMigrator = new IndividuallySchemaMigratorImpl(tool, null);
    135146        schemaMigrator.doMigration(metadata, schemaUpdates, schemaUpdates);
     
    170181          }
    171182          log.debug("Executing: " + sql.modified);
    172 
     183         
     184          currentSql = sql.modified;
    173185          stmt.executeUpdate(sql.modified);
     186          currentSql = null;
    174187
    175188          if (progress != null)
     
    195208    catch (SQLException | RuntimeException ex)
    196209    {
    197       log.error("Schema update failed", ex);
     210      if (currentSql != null)
     211      {
     212        log.error("Schema update failed while executing: " + currentSql, ex);
     213      }
     214      else
     215      {
     216        log.error("Schema update failed", ex);
     217      }
    198218      throw ex;
    199219    }
    200220    finally
    201221    {
     222      tableNameFormatter.resetWorkaroundForHibernateBug();
    202223      if (stmt != null)
    203224      {
     
    214235  }
    215236
     237 
    216238  /**
    217239    Get a list with the SQL statements that was ignored in the last run.
     
    386408  }
    387409 
     410
     411  /**
     412    Replace the 'QualifiedObjectNameFormatter' with an implementation that forces
     413    all table names to be flagged as quoted. This is a hack to work around a bug
     414    in Hibernate which generates "alter table table-name add column ..."
     415    statements without quotes around the table-name which causes an error
     416   
     417    TODO - When (if?) this issue is fixed in Hibernate we can remove this workaround
     418  */
     419  static class ForceQuotedTableNameFormatter
     420    implements QualifiedObjectNameFormatter
     421  {
     422
     423    private final Metadata metadata;
     424    private final JdbcEnvironment jdbc;
     425    private QualifiedObjectNameFormatter originalFormatter;
     426   
     427    ForceQuotedTableNameFormatter(Metadata metadata)
     428    {
     429      this.metadata = metadata;
     430      this.jdbc = metadata.getDatabase().getJdbcEnvironment();
     431    }
     432   
     433    @Override
     434    public String format(QualifiedTableName tableName, Dialect dialect)
     435    {
     436      QualifiedTableName quotedTableName = new QualifiedTableName(
     437        tableName.getCatalogName(),
     438        tableName.getSchemaName(),
     439        Identifier.toIdentifier(tableName.getTableName().getText(), true)
     440      );
     441      return originalFormatter.format(quotedTableName, dialect);
     442    }
     443
     444    @Override
     445    public String format(QualifiedSequenceName sequenceName, Dialect dialect)
     446    {
     447      return originalFormatter.format(sequenceName, dialect);
     448    }
     449
     450    @Override
     451    public String format(QualifiedName name, Dialect dialect)
     452    {
     453      return originalFormatter.format(name, dialect);
     454    }
     455   
     456    void applyWorkaroundForHibernateBug()
     457    {
     458      this.originalFormatter = jdbc.getQualifiedObjectNameFormatter();
     459      setFormatter(this);
     460    }
     461   
     462    void resetWorkaroundForHibernateBug()
     463    {
     464      if (originalFormatter != null) setFormatter(originalFormatter);
     465    }
     466   
     467    private void setFormatter(QualifiedObjectNameFormatter formatter)
     468    {
     469      try
     470      {
     471        Field f = JdbcEnvironmentImpl.class.getDeclaredField("qualifiedObjectNameFormatter");
     472        f.setAccessible(true);
     473        f.set(jdbc, formatter);
     474      }
     475      catch (Exception ex)
     476      {
     477        throw new RuntimeException(ex);
     478      }
     479    }
     480   
     481  }
     482 
    388483}
Note: See TracChangeset for help on using the changeset viewer.