org hibernate type SerializationException could not deserialize
This is very common exception if you are working with hibernate. This happens while you make call to the database where connection to the database is successful but while returning the data java model class for hibernate not able to deserialize and map the data. It occurs due to data mismatch and most of time I saw it happens for date attribute. Below is full details of exception:
Exception in thread “main” org.hibernate.type.SerializationException: could not deserialize
Caused by: java.io.StreamCorruptedException: invalid stream header: 0000A540
Exception in thread "main" org.hibernate.type.SerializationException: could not deserialize at org.hibernate.internal.util.SerializationHelper.doDeserialize(SerializationHelper.java:262) at org.hibernate.internal.util.SerializationHelper.deserialize(SerializationHelper.java:306) at org.hibernate.type.descriptor.java.SerializableTypeDescriptor.fromBytes(SerializableTypeDescriptor.java:155) at org.hibernate.type.descriptor.java.SerializableTypeDescriptor.wrap(SerializableTypeDescriptor.java:130) at org.hibernate.type.descriptor.java.SerializableTypeDescriptor.wrap(SerializableTypeDescriptor.java:44) at org.hibernate.type.descriptor.sql.VarbinaryTypeDescriptor$2.doExtract(VarbinaryTypeDescriptor.java:70) at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:64) at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:267) at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:263) at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253) at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:338) at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2969) at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1696) at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1628) at org.hibernate.loader.Loader.getRow(Loader.java:1515) at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:726) at org.hibernate.loader.Loader.processResultSet(Loader.java:953) at org.hibernate.loader.Loader.doQuery(Loader.java:921) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:355) at org.hibernate.loader.Loader.doList(Loader.java:2554) at org.hibernate.loader.Loader.doList(Loader.java:2540) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2370) at org.hibernate.loader.Loader.list(Loader.java:2365) at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:497) at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:387) at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:236) at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1300) at org.hibernate.internal.QueryImpl.list(QueryImpl.java:103) at com.javahonk.dao.InterestRateDaoHandler.getInterestRates(InterestRateDaoHandler.java:34) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) at com.sun.proxy.$Proxy33.getInterestRates(Unknown Source) at com.javahonk.SpringHibernateMultipleTestApp.main(SpringHibernateMultipleTestApp.java:42) Caused by: java.io.StreamCorruptedException: invalid stream header: 0000A540 at java.io.ObjectInputStream.readStreamHeader(Unknown Source) at java.io.ObjectInputStream.<init>(Unknown Source) at org.hibernate.internal.util.SerializationHelper$CustomObjectInputStream.<init>(SerializationHelper.java:328) at org.hibernate.internal.util.SerializationHelper$CustomObjectInputStream.<init>(SerializationHelper.java:318) at org.hibernate.internal.util.SerializationHelper.doDeserialize(SerializationHelper.java:237) ... 42 more
- Solution: You will have to properly deserialize the data in your model class. Below is two class which you can use one for LocalDate and another one for LocalDateTime:
LocalDateHibernateUserType.java:
package com.javahonk.model; import java.io.Serializable; import java.util.Date; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.type.StandardBasicTypes; import org.hibernate.usertype.EnhancedUserType; public class LocalDateHibernateUserType implements EnhancedUserType, Serializable{ private static final long serialVersionUID = -7500395414633111738L; private static final int[] sql_types = new int[]{Types.TIMESTAMP}; @Override public Object assemble(Serializable arg0, Object arg1) throws HibernateException { return arg0; } @Override public Object deepCopy(Object arg0) throws HibernateException { return arg0; } @Override public Serializable disassemble(Object arg0) throws HibernateException { return (Serializable) arg0; } @Override public boolean equals(Object obj1, Object obj2) throws HibernateException { if(obj1 == obj2) return true; if(obj1==null || obj2 == null) return false; LocalDate ldt1 = (LocalDate)obj1; LocalDate ldt2 = (LocalDate)obj2; return ldt1.equals(ldt2); } @Override public int hashCode(Object arg0) throws HibernateException { return arg0.hashCode(); } @Override public boolean isMutable() { return false; } @Override public Object nullSafeGet(ResultSet rs, String[] params, SessionImplementor session, Object owner) throws HibernateException, SQLException { Object timestamp = StandardBasicTypes.DATE.nullSafeGet(rs, params, session, owner); if(timestamp == null){ return null; } Date date = (Date) timestamp; Instant instant = Instant.ofEpochMilli(date.getTime()); return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()).toLocalDate(); } @Override public void nullSafeSet(PreparedStatement ps, Object value, int index, SessionImplementor session) throws HibernateException, SQLException { if(value==null){ StandardBasicTypes.DATE.nullSafeSet(ps, null, index, session); } else{ LocalDate ldt = (LocalDate) value; Instant instant = ldt.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant(); Date date = Date.from(instant); StandardBasicTypes.DATE.nullSafeSet(ps, date, index, session); } } @Override public Object replace(Object original, Object target, Object owner) throws HibernateException { return original; } @SuppressWarnings("rawtypes") @Override public Class returnedClass() { return LocalDate.class; } @Override public int[] sqlTypes() { return sql_types; } @Override public Object fromXMLString(String arg0) { return LocalDate.parse(arg0); } @Override public String objectToSQLString(Object arg0) { throw new UnsupportedOperationException(); } @Override public String toXMLString(Object arg0) { return arg0.toString(); } }
- LocalDateTimeHibernateUserType.java:
package com.javahonk.model; import java.io.Serializable; import java.util.Date; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.type.StandardBasicTypes; import org.hibernate.usertype.EnhancedUserType; public class LocalDateTimeHibernateUserType implements EnhancedUserType, Serializable{ private static final long serialVersionUID = 2769071855811042550L; private static final int[] sql_types = new int[]{Types.TIMESTAMP}; @Override public Object assemble(Serializable arg0, Object arg1) throws HibernateException { return arg0; } @Override public Object deepCopy(Object arg0) throws HibernateException { return arg0; } @Override public Serializable disassemble(Object arg0) throws HibernateException { return (Serializable) arg0; } @Override public boolean equals(Object obj1, Object obj2) throws HibernateException { if(obj1 == obj2) return true; if(obj1==null || obj2 == null) return false; LocalDateTime ldt1 = (LocalDateTime)obj1; LocalDateTime ldt2 = (LocalDateTime)obj2; return ldt1.equals(ldt2); } @Override public int hashCode(Object arg0) throws HibernateException { return arg0.hashCode(); } @Override public boolean isMutable() { return false; } @Override public Object nullSafeGet(ResultSet rs, String[] params, SessionImplementor session, Object owner) throws HibernateException, SQLException { Object timestamp = StandardBasicTypes.TIMESTAMP.nullSafeGet(rs, params, session, owner); if(timestamp == null){ return null; } Date ts = (Date) timestamp; Instant instant = Instant.ofEpochMilli(ts.getTime()); return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); } @Override public void nullSafeSet(PreparedStatement ps, Object value, int index, SessionImplementor session) throws HibernateException, SQLException { if(value==null){ StandardBasicTypes.TIMESTAMP.nullSafeSet(ps, null, index, session); } else{ LocalDateTime ldt = (LocalDateTime) value; Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant(); Date timestamp = Date.from(instant); StandardBasicTypes.TIMESTAMP.nullSafeSet(ps, timestamp, index, session); } } @Override public Object replace(Object original, Object target, Object owner) throws HibernateException { return original; } @SuppressWarnings("rawtypes") @Override public Class returnedClass() { return LocalDateTime.class; } @Override public int[] sqlTypes() { return sql_types; } @Override public Object fromXMLString(String arg0) { return LocalDateTime.parse(arg0); } @Override public String objectToSQLString(Object arg0) { throw new UnsupportedOperationException(); } @Override public String toXMLString(Object arg0) { return arg0.toString(); } }
Very important:
- Suppose you hibernate query is returning LocalDate and if attributes defined in model then you can use as below:
@Column(name="extracting_date") @Type(type = "com.javahonk.model.LocalDateHibernateUserType") private LocalDate extracting_date;
- If you are using LocalDateTime then please include in your model class as below:
@Column(name="extracting_date") @Type(type = "com.javahonk.model.LocalDateTimeHibernateUserType") private LocalDateTime extracting_date;
This should resolve above issue. For more information please visit here
thanks, thanks, thanks, thanks, thanks, thanks, thanks, thanks, thanks!!!