jdk1.8 日期新API LocalDateTime,LocalDate,LocalTime 在Hibernate中无法反序列化解决办法
jdk1.8 日期新API LocalDateTime,LocalDate,LocalTime 在Hibernate中无法反序列化解决方法
java JDK1.8 引入全新的时间日期API,但是无法结合Hibernate使用,hibernate源码并未对其进行支持,所以要使用hibernate的扩展进行支持。
以下是演示LocalDateTime如何使用,其余两个(LocalDate,LocalTime)的做法是一样的。
解决错误如下:
Caused by: org.hibernate.type.SerializationException: could not deserialize at org.hibernate.internal.util.SerializationHelper.doDeserialize(SerializationHelper.java:263) at org.hibernate.internal.util.SerializationHelper.deserialize(SerializationHelper.java:307) 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:2562) 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:2552) at org.hibernate.loader.Loader.doList(Loader.java:2538) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2368) at org.hibernate.loader.Loader.list(Loader.java:2363) at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:126) at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1724) at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:380) at oa.dao.CrudRepositoryImpl.findByCriteria(CrudRepositoryImpl.java:212) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:483) 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.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ... 66 more</span>
解决方法如下:
创建一个类对其进行支持
import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Date; import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.type.StandardBasicTypes; import org.hibernate.usertype.EnhancedUserType; public class LocalDateTimeType implements EnhancedUserType, Serializable { private static final long serialVersionUID = 2208831017183219350L; private static final int[] SQL_TYPES = new int[]{Types.TIMESTAMP};//指定在数据库中的类型 @Override public int[] sqlTypes() { return SQL_TYPES; } @Override public Class<?> returnedClass() { return LocalDateTime.class;//指定要反序列化的自定义类型 } @Override public boolean equals(Object x, Object y) throws HibernateException { if (x == y) { return true; } if (x == null || y == null) { return false; } LocalDateTime dtx = (LocalDateTime) x; LocalDateTime dty = (LocalDateTime) y; return dtx.equals(dty); } @Override public int hashCode(Object object) throws HibernateException { return object.hashCode(); } @Override public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException { Object timestamp = StandardBasicTypes.TIMESTAMP.nullSafeGet(resultSet, names, 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 preparedStatement, Object value, int index, SessionImplementor session) throws HibernateException, SQLException { if (value == null) { StandardBasicTypes.TIMESTAMP.nullSafeSet(preparedStatement, null, index, session); } else { LocalDateTime ldt = ((LocalDateTime) value); Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant(); Date timestamp = Date.from(instant); StandardBasicTypes.TIMESTAMP.nullSafeSet(preparedStatement, timestamp, index, session); } } @Override public Object deepCopy(Object value) throws HibernateException { return value; } @Override public boolean isMutable() { return false; } @Override public Serializable disassemble(Object value) throws HibernateException { return (Serializable) value; } @Override public Object assemble(Serializable cached, Object value) throws HibernateException { return cached; } @Override public Object replace(Object original, Object target, Object owner) throws HibernateException { return original; } @Override public String objectToSQLString(Object object) { throw new UnsupportedOperationException(); } @Override public String toXMLString(Object object) { return object.toString(); } @Override public Object fromXMLString(String string) { return LocalDateTime.parse(string); } }
在hibernate中的映射文件引用如下
<property name="属性名称" type="oa.common.type.LocalDateTimeType"> <span style="white-space:pre"> </span><column name="属性名称" sql-type="timestamp"> <span style="white-space:pre"> </span><comment>注释内容</comment> <span style="white-space:pre"> </span></column> </property>
在hibernate注解类添加如下注解
@TypeDefs({ @TypeDef(name = "localDateTimeType", defaultForType = LocalDateTime.class, typeClass = LocalDateTimeType.class ) })
@黄焕来
版权声明:本文为博主原创文章,未经博主允许不得转载。