排查JpaSystemException序列化失败问题求助
排查JPA序列化错误:could not serialize
遇到的错误信息:
org.springframework.orm.jpa.JpaSystemException: could not serialize; nested exception is org.hibernate.type.SerializationException: could not serialize
场景与相关代码
尝试将数据保存到数据库,核心代码如下:
public void logFailure(Long objectID,Integer usLK){ StatusFailureDO failureDO = new StatusFailureDO(4,objectID, usLK); failuresRepository.save(failureDO.getFailure()); } @Repository public interface FailuresRepository extends JpaRepository<GeneralFailure, Integer> { GeneralFailure save(GeneralFailure aGeneralFailure); void delete(GeneralFailure aGeneralFailure); GeneralFailure findByObjectID(Long objectID); }
此前已解决诸多映射错误,现需定位该错误的发生环节及排查方向,相关实体类代码如下:
public class StatusFailureDO extends GeneralFailureDO implements Serializable { public StatusFailureDO(Integer failureTypeLK,Long objectID, Integer usLK) { super(new StatusFailure(failureTypeLK, "An exception occurred while trying to update an UploadStatus entry.", objectID, usLK)); } //more constructors and setters } public abstract class GeneralFailureDO implements ICISConstant, Serializable { private GeneralFailure mGeneralFailure; //constructors and setters } @Entity @Inheritance(strategy = InheritanceType.JOINED) @Table(name = "GEN_FLR") public class GeneralFailure implements Serializable,ICISConstant { @Column(name = "CRTN_TM") private Date mCreationTime; @Column(name = "TYP_LKP_ID") private Integer failureTypeLK; @Column(name = "STUS_LKP_ID") private Integer mFailureStatusLK; @Column(name="OBJ_ID") @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "native") @GenericGenerator(name = "native", strategy = "native") private Long objectID; @Column(name = "DSCR") private String mDescription; public Date getCreationTime() { return mCreationTime; } public void setCreationTime(Date aCreationTime) { mCreationTime = aCreationTime; } public String getDescription() { return mDescription; } public void setDescription(String aDescription) { if (aDescription != null && aDescription.length() > MAX_DESCRIPTION_LENGTH) { mDescription = aDescription.substring(0, MAX_DESCRIPTION_LENGTH); } else { mDescription = aDescription; } } public Long getObjectID() { return objectID; } public void setObjectID(Long aObjectID) { objectID = aObjectID; } public Integer getFailureTypeLK() { return failureTypeLK; } public void setFailureTypeLK(Integer aFailureTypeLK) { failureTypeLK = aFailureTypeLK; } public Integer getFailureStatusLK() { return mFailureStatusLK; } public void setFailureStatusLK(Integer aFailureStatusLK) { mFailureStatusLK = aFailureStatusLK; } } @Entity @Table(name="STUS_FLR") public class StatusFailure extends GeneralFailure implements Serializable { @Column(name = "STUS_OBJ_ID") private Long mStatusObjectID; @Column(name = "STUS_LKP_ID") private Integer mStatusLK; @Column(name = "RQST_TYP_LKP_ID") private Integer mRequestTypeLK; @Column(name = "CODE") private String mCode; @Column(name = "PST_TM") private Timestamp mPostTime; @Column(name = "MSG_SZ") private Integer mMessageSize; @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) private Collection<StatusFailureError> StatusFailureErrorList; @Column(name = "SMPL_FLG") private boolean mSimple; public Integer getStatusLK() { return mStatusLK; } public void setStatusLK(Integer statusLK) { mStatusLK = statusLK; } public Long getStatusObjectID() { return mStatusObjectID; } public void setStatusObjectID(Long statusObjectID) { mStatusObjectID = statusObjectID; } public String getCode() { return mCode; } public void setCode(String aCode) { mCode = aCode; } public Collection<StatusFailureError> getStatusFailureErrorList() { return StatusFailureErrorList; } public void setStatusFailureErrorList(Collection<StatusFailureError> aStatusFailureErrorList) { StatusFailureErrorList = aStatusFailureErrorList; } public void setErrorList(Collection<String> aErrorList) { if (aErrorList != null && !aErrorList.isEmpty()) { StatusFailureErrorList = new ArrayList<StatusFailureError>(); for (Iterator<String> iter = aErrorList.iterator(); iter.hasNext();) { String error = (String) iter.next(); StatusFailureError failureError = new StatusFailureError(this, error, getPostTime()); StatusFailureErrorList.add(failureError); } } else { StatusFailureErrorList = null; } } public Integer getMessageSize() { return mMessageSize; } public void setMessageSize(Integer aMessageSize) { mMessageSize = aMessageSize; } public Timestamp getPostTime() { return mPostTime; } public void setPostTime(Timestamp aPostTime) { mPostTime = aPostTime; } public Integer getRequestTypeLK() { return mRequestTypeLK; } public void setRequestTypeLK(Integer aRequestTypeLK) { mRequestTypeLK = aRequestTypeLK; } public boolean isSimple() { return mSimple; } public void setSimple(boolean aSimple) { mSimple = aSimple; } }
错误发生环节
该错误一般出现在Hibernate对实体进行序列化的阶段,主要场景包括:
- 持久化实体前的对象预处理环节
- 实体写入二级缓存时的序列化操作
排查方向
- 检查关联类的序列化实现:
- 确认
StatusFailureError类(代码中未提供完整实现)是否实现了Serializable接口,因为StatusFailure中关联了该类的集合,若未序列化会导致整个对象无法完成序列化。 - 核实所有实体的父类(如
ICISConstant的实现类)是否存在非序列化的成员变量,确保整个继承链的序列化合规。
- 确认
- 验证字段类型的兼容性:
- 检查实体中所有字段的类型是否为JPA/Hibernate支持的可序列化类型,虽然
Date、Timestamp本身可序列化,但需确认是否有自定义复杂类型未正确配置映射。 - 确认
Collection<StatusFailureError>的具体实现类(如ArrayList)是可序列化的,且集合内元素均满足序列化要求。
- 检查实体中所有字段的类型是否为JPA/Hibernate支持的可序列化类型,虽然
- 排查懒加载关联的初始化问题:
- 尽管
StatusFailureErrorList配置为懒加载,但如果保存操作触发了该集合的初始化(比如某些隐式操作导致Hibernate加载关联对象),而关联对象未序列化,也会引发错误。可暂时移除该关联测试,验证是否还报错。
- 尽管
- 手动测试序列化:
- 编写简单测试代码,手动将
StatusFailure实例序列化为字节流再反序列化,观察是否抛出NotSerializableException,快速定位具体的问题类或字段。
- 编写简单测试代码,手动将
- 检查ID生成策略的序列化一致性:
- 确认
native生成器生成的Long类型主键在序列化前后保持一致,避免因ID字段导致的序列化异常。
- 确认
内容的提问来源于stack exchange,提问作者FigureCodeOut
相关产品推荐
相关产品推荐

