java.lang.ClassCastException: java.math.cannot be cast to java.lang.Long while starting server

I am upgrading hibernate version from 5.1.17 to 5.4.11 and mssql-jdbc version to 7.2.2.jre8 . I am connecting to MS sql server

But while starting the server , I am getting below error message

Caused by: java.sql.SQLException: An SQLException was provoked by the following failure: java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.Long
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:118)
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:77)
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:74)
at com.mchange.v2.c3p0.impl.NewPooledConnection.handleThrowable(NewPooledConnection.java:505)
at com.mchange.v2.c3p0.impl.NewProxyResultSet.getLong(NewProxyResultSet.java:491)
at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.resultSetStartValueSize(SequenceInformationExtractorLegacyImpl.java:129)
at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:59)
at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:65)
at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.(DatabaseInformationImpl.java:59)
at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:155)
… 127 more
Caused by: java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.Long
at com.microsoft.sqlserver.jdbc.SQLServerResultSet.getLong(SQLServerResultSet.java:2328)
at com.mchange.v2.c3p0.impl.NewProxyResultSet.getLong(NewProxyResultSet.java:477)
… 132 more

Can you please some one help me with this ?

In my opinion that is a bug in Hibernate (see also https://hibernate.atlassian.net/browse/HHH-13805 and https://discourse.hibernate.org/t/sql-server-could-not-fetch-the-sequenceinformation-from-the-database/4083). In SQL Server sequences are typed that is they can be int, smallint, long, … That is reflected in the meta data returned by the INFORMATION_SCHEMA.SEQUENCES view. However, Hibernate assumes that the schema columns holding the min, max and current values for the sequence are always of type long. That is not the case. They are holding and returning values of the type of the defined sequence. I recently had to work around that problem and wrote my own custom dialect with a custom implementation of the SequenceInformationExtractorLegacyImpl class that deals with the multiple types.

1 Like

Thanks for information. Can you please share work around code with me ?

Create a class like this

package ....;

import org.hibernate.dialect.SQLServer2012Dialect;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;

/**
 * Custom SQLServer dialect to deal with SEQUENCE schema query result processing issue
 */
public class SQLServerCustomDialect extends SQLServer2012Dialect {

  @Override
  public SequenceInformationExtractor getSequenceInformationExtractor() {
    if ( getQuerySequencesString() == null ) {
      return SequenceInformationExtractorNoOpImpl.INSTANCE;
    }
    else {
      return SequenceInformationExtractorImpl.INSTANCE;
    }
  }

}

Set this class as the hibernate dialect in your persistence.xml or whereever you configure hibernate.

Create this class

/*
 * 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>.
 *
 * Adapted from the class with the same name in the Hibernate distribution.
 */

package ...;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.boot.model.relational.QualifiedSequenceName;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
import org.hibernate.tool.schema.extract.internal.SequenceInformationImpl;
import org.hibernate.tool.schema.extract.spi.ExtractionContext;
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;

/**
 * @author Steve Ebersole
 */
public class SequenceInformationExtractorImpl implements SequenceInformationExtractor {
  /**
   * Singleton access
   */
  public static final SequenceInformationExtractorImpl INSTANCE = new SequenceInformationExtractorImpl();

  @Override
  public Iterable<SequenceInformation> extractMetadata(final ExtractionContext extractionContext) throws SQLException {
    final String lookupSql = extractionContext.getJdbcEnvironment().getDialect().getQuerySequencesString();

    // *should* never happen, but to be safe in the interest of performance...
    if ( lookupSql == null ) {
      return SequenceInformationExtractorNoOpImpl.INSTANCE.extractMetadata( extractionContext );
    }

    final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper();
    final Statement statement = extractionContext.getJdbcConnection().createStatement();
    try {
      final ResultSet resultSet = statement.executeQuery( lookupSql );
      try {
        final List<SequenceInformation> sequenceInformationList = new ArrayList<>();
        while ( resultSet.next() ) {
          sequenceInformationList.add(
              new SequenceInformationImpl(
                  new QualifiedSequenceName(
                      identifierHelper.toIdentifier(
                        resultSetCatalogName( resultSet )
                      ),
                      identifierHelper.toIdentifier(
                          resultSetSchemaName( resultSet )
                      ),
                      identifierHelper.toIdentifier(
                          resultSetSequenceName( resultSet )
                      )
                  ),
                  resultSetStartValueSize( resultSet ),
                  resultSetMinValue( resultSet ),
                  resultSetMaxValue( resultSet ),
                  resultSetIncrementValue( resultSet )
              )
          );
        }
        return sequenceInformationList;
      }
      finally {
        try {
          resultSet.close();
        }
        catch (final SQLException ignore) {
        }
      }
    }
    finally {
      try {
        statement.close();
      }
      catch (final SQLException ignore) {
      }
    }
  }

  protected String sequenceNameColumn() {
    return "sequence_name";
  }

  protected String sequenceCatalogColumn() {
    return "sequence_catalog";
  }

  protected String sequenceSchemaColumn() {
    return "sequence_schema";
  }

  protected String sequenceStartValueColumn() {
    return "start_value";
  }

  protected String sequenceMinValueColumn() {
    return "minimum_value";
  }

  protected String sequenceMaxValueColumn() {
    return "maximum_value";
  }

  protected String sequenceIncrementColumn() {
    return "increment";
  }

  protected String resultSetSequenceName(final ResultSet resultSet) throws SQLException {
    return resultSet.getString( sequenceNameColumn() );
  }

  protected String resultSetCatalogName(final ResultSet resultSet) throws SQLException {
    final String column = sequenceCatalogColumn();
    return column != null ? resultSet.getString( column ) : null;
  }

  protected String resultSetSchemaName(final ResultSet resultSet) throws SQLException {
    final String column = sequenceSchemaColumn();
    return column != null ? resultSet.getString( column ) : null;
  }

  protected Long resultSetStartValueSize(final ResultSet resultSet) throws SQLException {
    final String column = sequenceStartValueColumn();
    return column != null ? resultSetGetAsLong( resultSet, column ) : null;
  }

  protected Long resultSetMinValue(final ResultSet resultSet) throws SQLException {
    final String column = sequenceMinValueColumn();
    return column != null ? resultSetGetAsLong( resultSet, column ) : null;
  }

  protected Long resultSetMaxValue(final ResultSet resultSet) throws SQLException {
    final String column = sequenceMaxValueColumn();
    return column != null ? resultSetGetAsLong( resultSet, column ) : null;
  }

  protected Long resultSetIncrementValue(final ResultSet resultSet) throws SQLException {
    final String column = sequenceIncrementColumn();
    return column != null ? resultSetGetAsLong( resultSet, column ) : null;
  }

  private Long resultSetGetAsLong(final ResultSet resultSet, final String column) throws SQLException {
    final Object value = resultSet.getObject(column);
    if (value == null || !(value instanceof Number)) {
      return null;
    }
    return ((Number)value).longValue();
  }
}
1 Like

Thank you so much for sharing. Let me try the same.