I am using Hibernate 4.3.4 with Envers, and MySql 5.6.
Without a JPA 2.1 converter, the Party
entity below fails at Configuration.buildSessionFactory()
as it should, since Hibernate doesn't know what to do with the Name class:
@Entity
@Audited
public class Party
{
protected Name name;
...
}
The exception is:
org.hibernate.MappingException:
Could not determine type for:
ModuloADM.Party.Name,
at table: Party, for columns: [org.hibernate.mapping.Column(name)]
To fix this, I then add this converter:
@Converter (autoApply=true)
public class NametoStringConverter
implements AttributeConverter<Name, String>
{ ... }
And the exception now changes to:
org.hibernate.MappingException:
Could not determine type for:
BasicType adapter for AttributeConverter<Name,String>,
at table: History_Party, for columns: [org.hibernate.mapping.Column(name)]
This is now failing at the Envers auditing table for the Party
entity. Note that History_Party
is the name of the audit table, as chosen by config.setProperty("org.hibernate.envers.audit_table_prefix", "History_")
.
The complete stacktrace is:
org.hibernate.MappingException:
Could not determine type for:
BasicType adapter for AttributeConverter<Name,String>,
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.<init>(EntityMetamodel.java:227)
at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:520)
at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(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.<init>(SessionFactoryImpl.java:401)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1857)
How do I solve this? Is Envers even compatible with AttributeConverters?
Try using @Convert in Party
Entity. Sometimes autoApply
flag will not work
@Entity
@Audited
public class Party
{
@Convert(converter = NametoStringConverter.class)
protected Name name;
...
}
This seems to be a known problem with Hibernate Envers (HHH-9042).
A simple workaround would be a manual invocation of the Convter and an additional transient field, like this:
@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;
}
}
Depending on the conversion functions, the code could be further simplified by making them static
and importing them.
I see the text "GeneratedConstructorAccessor43" in the exception. May be you need a public void constructor so that JPA can create an instance of NametoStringConverter.
The default constructor should work but check if you have another one with receives parameters or not public.
I had the same problem, what I found out that it only occured when I didn't put the @Column annotation with columnDefinition = "VARCHAR(255)" to the Enum. So I think that is a better work around than what in hibernate tracker has.
来源:https://stackoverflow.com/questions/22358912/hibernate-envers-fails-with-converter-and-attributeconverter-jpa-2-1