Reputation: 30879
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?
Upvotes: 8
Views: 12043
Reputation: 95
In case you need to specify a column name for the column (in this example "C_NAME") you need to add @Column annotation.
@Entity
@Audited
public class Party
{
@Convert(converter = NametoStringConverter.class)
@Column( name = "C_NAME" )
protected Name name;
...
}
Note below code will not work and will result in "Could not determine type for: " error because Converter annotation will be ignored.
@Entity
@Audited
public class Party
{
@Convert(converter = NametoStringConverter.class)
@Column( name = "C_NAME", nullable=true ) // DOESN'T WORK
protected Name name;
...
}
Upvotes: 0
Reputation: 85
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.
Upvotes: 0
Reputation: 4614
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.
Upvotes: 1
Reputation: 11655
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.
Upvotes: 0
Reputation: 21883
Try using @Convert in Party
Entity. Sometimes autoApply
flag will not work
@Entity
@Audited
public class Party
{
@Convert(converter = NametoStringConverter.class)
protected Name name;
...
}
Upvotes: 1