Nick Williams commented on Bug HHH-8111

In my attached sample, I had failed to annotate the AttributeConverter implementation with @Converter. (I had done this in my real application, but in my simple test case forgot it.) I get a different exception now that I've added it. It doesn't matter whether I annotate it @Converter, @Converter(autoApply = false), or @Converter(autoApply = true), I get the same exception:

javax.persistence.PersistenceException: org.hibernate.HibernateException: Unknown unwrap conversion requested: java.lang.StackTraceElement to java.lang.String
	at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1561)
	at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1486)
	at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1492)
	at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1002)
	at net.nicholaswilliams.java.TestClass.persistComplexEntities(TestClass.java:90)
	at net.nicholaswilliams.java.TestClass.main(TestClass.java:135)
Caused by: org.hibernate.HibernateException: Unknown unwrap conversion requested: java.lang.StackTraceElement to java.lang.String
	at org.hibernate.type.descriptor.java.AbstractTypeDescriptor.unknownUnwrap(AbstractTypeDescriptor.java:103)
	at org.hibernate.type.descriptor.java.SerializableTypeDescriptor.unwrap(SerializableTypeDescriptor.java:114)
	at org.hibernate.type.descriptor.java.SerializableTypeDescriptor.unwrap(SerializableTypeDescriptor.java:44)
	at org.hibernate.type.descriptor.sql.VarcharTypeDescriptor$1.doBind(VarcharTypeDescriptor.java:64)
	at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:93)
	at org.hibernate.mapping.SimpleValue$AttributeConverterSqlTypeDescriptorAdapter$1.doBind(SimpleValue.java:491)
	at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:93)
	at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:281)
	at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:276)
	at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:56)
	at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2793)
	at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2768)
	at org.hibernate.persister.entity.AbstractEntityPersister$4.bindValues(AbstractEntityPersister.java:2975)
	at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:57)
	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2982)
	at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3494)
	at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:97)
	at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:364)
	at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:205)
	at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:185)
	at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:169)
	at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:322)
	at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:287)
	at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
	at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:126)
	at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84)
	at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:209)
	at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:152)
	at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:79)
	at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:854)
	at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:828)
	at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:832)
	at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:996)
	... 2 more

Stepping through the code again, it appears what happened is Hibernate DID recognize my converter and DID call convertToDatabaseColumn in org.hibernate.mapping.SimpleValue$AttributeConverterSqlTypeDescriptorAdapter$1.doBind, and in the highest call to org.hibernate.type.descriptor.sql.BasicBinder.bind the value changed from a StackTraceElement to a String. This String should be able to be persisted to a VARCHAR column. However, the org.hibernate.type.descriptor.java.SerializableTypeDescriptor.unwrap method only allows types byte[], InputStream, BinaryStream and Blob.

On a hunch, based on the bug description, I changed the return type / argument type of the entity's Location field accessor/mutator from StackTraceElement to Object, and changed the AttributeConverter so that it converts Objects instead of StackTraceElement (just calling toString()). Now it uses a different, random persistence strategy every time. Once it's BigDecimalTypeDescriptor, then it's ShortTypeDescriptor, then it's ArrayMutabilityPlan, then it's BlobTypeDescriptor$BlobMutabilityPlan, and so on. Each time I run it it picks a random plan, sometimes repeating, sometimes not.

It appears Hibernate is trying to determine how to persist the field based on the field type (in this example, first StackTraceElement, later Object) instead of the return type of the converter (in this example, String). If I change the field type to some other class that isn't Serializable and isn't castable to one of the types Hibernate natively supports (in this case, custom class SpecialType), it works. Hibernate should formulate a persistence strategy based on the return type of the converter.

I repeat the question from the previous comment. Can this be fixed for beta3?

This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira