Hibernate Envers fallisce con @Converter e AttributeConverter (JPA 2.1)

Sto usando Hibernate 4.3.4 con Envers e MySql 5.6.

Senza un convertitore JPA 2.1, l’ quadro Party seguito non riesce a Configuration.buildSessionFactory() come dovrebbe, poiché Hibernate non sa cosa fare con la class Name:

 @Entity @Audited public class Party { protected Name name; ... } 

L’eccezione è:

 org.hibernate.MappingException: Could not determine type for: ModuloADM.Party.Name, at table: Party, for columns: [org.hibernate.mapping.Column(name)] 

Per risolvere il problema, aggiungo quindi questo convertitore:

 @Converter (autoApply=true) public class NametoStringConverter implements AttributeConverter { ... } 

E l’eccezione ora cambia in:

 org.hibernate.MappingException: Could not determine type for: BasicType adapter for AttributeConverter, at table: History_Party, for columns: [org.hibernate.mapping.Column(name)] 

Questo ora non funziona nella tabella di controllo Envers per l’ quadro Party . Nota che History_Party è il nome della tabella di controllo, come scelto da config.setProperty("org.hibernate.envers.audit_table_prefix", "History_") .

Lo stacktrace completo è:

 org.hibernate.MappingException: Could not determine type for: BasicType adapter for AttributeConverter, at table: History_Party, for columns: [org.hibernate.mapping.Column(name)] at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:336) at org.hibernate.tuple.PropertyFactory.buildEntityBasedAttribute(PropertyFactory.java:246) at org.hibernate.tuple.entity.EntityMetamodel.(EntityMetamodel.java:227) at org.hibernate.persister.entity.AbstractEntityPersister.(AbstractEntityPersister.java:520) at org.hibernate.persister.entity.SingleTableEntityPersister.(SingleTableEntityPersister.java:148) at sun.reflect.GeneratedConstructorAccessor43.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:525) at org.hibernate.persister.internal.PersisterFactoryImpl.create(PersisterFactoryImpl.java:163) at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:135) at org.hibernate.internal.SessionFactoryImpl.(SessionFactoryImpl.java:401) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1857) 

Come lo risolvo? Envers è persino compatibile con AttributeConverters?

Prova a utilizzare @Convert in Party Entity. A volte il flag autoApply non funziona

 @Entity @Audited public class Party { @Convert(converter = NametoStringConverter.class) protected Name name; ... } 

Questo sembra essere un problema noto con Hibernate Envers (HHH-9042) .

Una soluzione semplice sarebbe un’invocazione manuale di Convter e un campo transitorio aggiuntivo, come questo:

 @Entity public class Party { protected Name name; @Transient protected String nameString; //... public void setName(Name name) { this.nameString = (new NametoStringConverter()).convertToDatabaseColumn(name); this.name = name; } //... public void setNameString(String nameString) { this.name = (new NametoStringConverter()).convertToEntityAttribute(nameString); this.nameString = nameString; } } 

A seconda delle funzioni di conversione, il codice potrebbe essere ulteriormente semplificato rendendoli static e importandoli.

Vedo il testo “GeneratedConstructorAccessor43” nell’eccezione. Potrebbe essere necessario un costruttore pubblico di void in modo che JPA possa creare un’istanza di NametoStringConverter.

Il costruttore predefinito dovrebbe funzionare ma controllare se ne hai un altro con parametri di ricezione o non pubblico.

Ho avuto lo stesso problema, quello che ho scoperto che si è verificato solo quando non ho messo l’annotazione @Column con columnDefinition = “VARCHAR (255)” all’Enum. Quindi penso che sia un lavoro migliore rispetto a quello che ha in Hibernate Tracker.