We're updating the issue view to help you get more done. 

Allow AttributeConverter on attributes marked as Lob (REALLY this time)

Description

I believe is not done. The test case there converts String to Integer, to represent it as Lob, but these are both basic regular types. If instead of a String you use something else (some custom Class), it doesn't seem to work.

For example, here I use a class called Imagem, and convert it to a String:

1 2 3 4 5 6 7 8 9 10 11 12 13 @Converter public class ImagemToString_Converter implements AttributeConverter<Imagem, String> { public String convertToDatabaseColumn(@Nullable Imagem attribute) { if (attribute== null) return null; return attribute.toString(); } public Imagem convertToEntityAttribute(@Nullable String dbData) { return Imagem.getInstance(dbData); } }

The above code works OK as long as the field is not a @Lob (which means the converter itself is correct). But as soon as I add @Lob to the field it stops working. For example:

1 2 @Lob protected Imagem fotografia;

Then, when I try to save, it should see a String (the converter gets called), but it still sees an Imagem, and then I get this:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 java.lang.ClassCastException: Imagem.Imagem cannot be cast to org.hibernate.engine.jdbc.CharacterStream at org.hibernate.type.descriptor.sql.ClobTypeDescriptor$4$1.doBind(124) at org.hibernate.type.descriptor.sql.BasicBinder.bind(74) at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(277) at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(272) at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(39) at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(2646) at org.hibernate.persister.entity.AbstractEntityPersister.insert(2931) at org.hibernate.persister.entity.AbstractEntityPersister.insert(3434) at org.hibernate.action.internal.EntityInsertAction.execute(89) at org.hibernate.engine.spi.ActionQueue.executeActions(560) at org.hibernate.engine.spi.ActionQueue.executeActions(434) at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(337) at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(39) at org.hibernate.internal.SessionImpl.flush(1396) at org.hibernate.internal.SessionImpl.managedFlush(472) at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(3132) at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(2369) at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(467) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(147) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(38) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(221) at org.hibernate.engine.transaction.internal.TransactionImpl.commit(68) at Http.Sessao.SessaoETransacaoHibernate.comitaATransaçãoCasoExistaTransaçãoAtiva(SessaoETransacaoHibernate.java:28) at Http.Sessao.Filtro$ProcessadorDeRequest.processaRequest(Filtro.java:267) at Http.Sessao.Filtro$ProcessadorDeRequest.access$100(Filtro.java:91) at Http.Sessao.Filtro.doFilter(Filtro.java:594) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(206) at org.apache.catalina.core.StandardWrapperValve.invoke(219) at org.apache.catalina.core.StandardContextValve.invoke(106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(502) at org.apache.catalina.core.StandardHostValve.invoke(142) at org.apache.catalina.valves.ErrorReportValve.invoke(79) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(617) at org.apache.catalina.core.StandardEngineValve.invoke(88) at org.apache.catalina.connector.CoyoteAdapter.service(518) at org.apache.coyote.http11.AbstractHttp11Processor.process(1091) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(668) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(2463) at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(2452) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(61) at java.lang.Thread.run(Thread.java:745)

If I save it to the database without @Lob, and then add the @Lob and try to open it, I get this:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 org.hibernate.PropertyAccessException: Could not set field value [com.mysql.jdbc.Clob@4b881040] value by reflection : [class ModuloADM.Usuario.Usuario.fotografia] setter of ModuloADM.Usuario.Usuario.fotografia at org.hibernate.property.access.spi.SetterFieldImpl.set(58) at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(610) at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(205) at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(4618) at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(169) at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(125) at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.performTwoPhaseLoad(238) at org.hibernate.loader.plan.exec.process.internal.AbstractRowReader.finishUp(209) at org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl.extractResults(133) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(122) at org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader.executeLoad(86) at org.hibernate.loader.entity.plan.AbstractLoadPlanBasedEntityLoader.load(167) at org.hibernate.persister.entity.AbstractEntityPersister.load(4004) at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(508) at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(478) at org.hibernate.event.internal.DefaultLoadEventListener.load(219) at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(278) at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(121) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(89) at org.hibernate.internal.SessionImpl.fireLoad(1212) at org.hibernate.internal.SessionImpl.access$1900(204) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.doLoad(2752) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(2726) at org.hibernate.internal.SessionImpl.get(1048) at sun.reflect.NativeMethodAccessorImpl.invoke0(sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(43) at java.lang.reflect.Method.invoke(Method.java:483) at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(338) at com.sun.proxy.$Proxy64.get(com.sun.proxy.$Proxy64.get(Unknown Source) at Objetos.Registro.Registro_Dao.busca(Registro_Dao.java:202) ... Caused by: java.lang.IllegalArgumentException: Can not set Imagem.Imagem field ModuloADM.Usuario.Usuario.fotografia to com.mysql.jdbc.Clob at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(167) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(171) at sun.reflect.UnsafeObjectFieldAccessorImpl.set(81) at java.lang.reflect.Field.set(Field.java:758) at org.hibernate.property.access.spi.SetterFieldImpl.set(38) ...

Environment

None

Status

Assignee

Steve Ebersole

Reporter

Marcelo Glasberg

Fix versions

Labels

backPortable

None

Suitable for new contributors

None

Requires Release Note

None

Pull Request

None

backportDecision

None

Components

Affects versions

5.2.0
5.1.0

Priority

Major