问题
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?
回答1:
Try using @Convert in Party
Entity. Sometimes autoApply
flag will not work
@Entity
@Audited
public class Party
{
@Convert(converter = NametoStringConverter.class)
protected Name name;
...
}
回答2:
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.
回答3:
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.
回答4:
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