3 Replies Latest reply on Sep 28, 2012 11:04 AM by roge.delgado

    Envers problem using AbstractSingleColumnStandardBasicType

    roge.delgado

      Hi all, I'm new here, and my english could be better, but here I go.

       

      I'm having troubles with Envers and custom data types. In my project we have a requirement of using UUID for some entities as ID's but we must support three different database vendors (PostgreSQL, MySQL and SQL Server). The tables that these entities map are considerably large so storing the UUID like varchar are a performance issue for us, so we decided to use native UUID data types according to the specific database,  i.e. PostgreSQL has support for this whit his "uuid" data type, SQL Server has support also with his "uniqueidentifier" data type, but MySQL (at least until the version 5.5.24) has no support for this kind of data type. To avoid this, we develop a custom type that depending of the database used (depending of the Hibernate dialect) the java.util.UUID type is mapped to some specific database data type. We follow this post to do that:

      https://zorq.net/b/2012/04/21/switching-hibernates-uuid-type-mapping-per-database/

       

       

      To be honest, I don't completely understand why the post used the AbstractSingleColumnStandardBasic<T> class (by the way, somebody can point me to some pice of documentation about that class?), but I'm successfully able to perform writes and reads for each database that we must support. The problem comes when I add the @Audited anotation to the entity with the UUID id field. Hibernate throws a exception saying:

       

      Caused by: org.hibernate.MappingException: Could not determine type for: uuid-custom, at table: payment_conditions_aud, for columns: [org.hibernate.mapping.Column(id)]
          at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:305)
          at org.hibernate.mapping.Column.getSqlTypeCode(Column.java:187)
          at org.hibernate.mapping.Column.getSqlType(Column.java:227)
          at org.hibernate.mapping.Table.sqlTemporaryTableCreateString(Table.java:384)
          at org.hibernate.mapping.PersistentClass.prepareTemporaryTables(PersistentClass.java:779)
          at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:341)
          at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1744)
          at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94)
          at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905)
          ... 74 more
      

       

      This is my entity:

      @Entity
      @Table(name = "payment_conditions")
      public class PaymentCondition implements Serializable {
          private static final long serialVersionUID = 1L;
      
          @Id
          @Type(type = "mx.ssf.sicom.commondomain.util.UUIDCustomType")
          @Column(name = "id")
          private UUID id;
      
          @NotNull
          @Column(name = "code", unique = true)
          @Audited
          private String code;
      
          @Enumerated(EnumType.STRING)
          @NotNull
          @Audited
          private PAYMENT_TYPE type;
      
          @NotNull
          @Audited
          private String reference;
      
          @Column(name = "payment_until_days")
          @Audited
          private int paymentUntilDays;
      
          @Column(name = "active")
          @Audited
          private Boolean active;
      
          // bi-directional many-to-one association to PrintingType
          @ManyToOne(fetch = FetchType.LAZY)
          @JoinColumn(name = "printing_type_id")
          @Audited(targetAuditMode=RelationTargetAuditMode.NOT_AUDITED)
          private PrintingType printingType;
      
      //Getters and setter 
      }
      

       

      And this is my AbstractSingleColumnStandardBasic extension:

       

      public class UUIDCustomType extends AbstractSingleColumnStandardBasicType<UUID> {
      
          private static final long serialVersionUID = 1L;
          private static SqlTypeDescriptor SQL_DESCRIPTOR;
          private static JavaTypeDescriptor<UUID> TYPE_DESCRIPTOR;
          private static final String MESSAGE_ERROR = "Some error string";
      
          static {
              Properties properties = new Properties();
      
              //Here goes the code to load the properties where the "dialect" is defined based on the different databases
      
              String dialect = properties.getProperty("db.vendor.databasePlatformDialect");
              if (dialect.equals("org.hibernate.dialect.PostgreSQLDialect")) {
                  SQL_DESCRIPTOR = PostgresUUIDType.PostgresUUIDSqlTypeDescriptor.INSTANCE;
              } else {
                  SQL_DESCRIPTOR = VarcharTypeDescriptor.INSTANCE;
              }
      
              TYPE_DESCRIPTOR = UUIDTypeDescriptor.INSTANCE;
          }
      
          public UUIDCustomType() {
              super(SQL_DESCRIPTOR, TYPE_DESCRIPTOR);
          }
      
          public String getName() {
              return "uuid-custom";
          }
      }
      

       

      So, after trying to track down what's going on here I can't find a way to make the auditing work. Anybody can tell me what I'm doing wrong? I hope that my issue will be clear enough. Please let me know if a clarification is needed.

       

      Thanks in advance.

       

      Rogelio