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

Hibernate incorrectly defaults all Serializable types to VARBINARY in SqlTypeDescriptorRegistry

    Details

    • Type: Improvement
    • Status: Open
    • Priority: Major
    • Resolution: Unresolved
    • Affects versions: 4.3.7
    • Fix versions: None
    • Components: hibernate-core
    • Labels:
      None
    • Last commented by a user?:
      true
    • Sprint:

      Description

      I'm looking into working around an issue related to Oracle DATE data types and java.sql.Timestamp bind values, which are applied by Hibernate (or pretty much any other database API, such as jOOQ) by default for timestamp information. The Oracle issue is documented here:

      With Hibernate, I can either use the proprietary UserType API (explained in the first article), or I should be able to use JPA 2.1 converters to force an oracle.sql.DATE bind value, which also helps circumventing the original issue:

      import java.sql.Timestamp;
       
      import javax.persistence.AttributeConverter;
      import javax.persistence.Converter;
       
      import oracle.sql.DATE;
       
      @Converter
      public class OracleDateConverter 
      implements AttributeConverter<Timestamp, DATE>{
       
          @Override
          public DATE convertToDatabaseColumn(Timestamp attribute) {
              return attribute == null ? null : new DATE(attribute);
          }
       
          @Override
          public Timestamp convertToEntityAttribute(DATE dbData) {
              return dbData == null ? null : dbData.timestampValue();
          }
      }
      

      Unfortunately, Hibernate treats all Serializable types as VARBINARY as can be seen here:

      // From org.hibernate.type.descriptor.sql.SqlTypeDescriptorRegistry
       
          public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
              if ( Serializable.class.isAssignableFrom( javaTypeDescriptor.getJavaTypeClass() ) ) {
                  return VarbinaryTypeDescriptor.INSTANCE.getBinder( javaTypeDescriptor );
              }
       
              return new BasicBinder<X>( javaTypeDescriptor, this ) {
                  @Override
                  protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
                          throws SQLException {
                      st.setObject( index, value, jdbcTypeCode );
                  }
              };
          }
      

      I think this is a bit too clever on the Hibernate side. If I wanted that behaviour, I can still implement a AttributeConverter<Timestamp, byte[]> and implement the three lines of serialisation code myself.

      However, by defaulting to VARBINARY inside of Hibernate, I'm deprived of using a lot of vendor-specific JDBC types, such as this one INTERVAL types, or TIMESTAMPTZ, or all the various PostgreSQL PGobject, PGgeometry, PGbox, PGcircle, or even simple array types, which I don't want to be Java-serialized, but simply passed through to the server via PreparedStatement.setObject().

      Note that this behaviour is not at all specified in AttributeConverter

        Attachments

          Activity

            People

            • Assignee:
              Unassigned
              Reporter:
              lukas.eder Lukas Eder
              Participants:
            • Votes:
              2 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated: