Hibernate Envers结合PostgreSQL枚举映射部署报错求助
解决Hibernate Envers搭配@Enumerated(EnumType.STRING)在Glassfish 5.0的ClassCastException问题
我之前在Glassfish环境下搭配Hibernate Envers处理枚举类型时,碰到过一模一样的报错,这本质是Hibernate Envers 5.2.x版本在处理字符串枚举映射时的兼容问题,结合Glassfish的类加载机制就触发了类型转换异常。给你几个可行的解决思路:
1. 升级Hibernate版本(最推荐)
这个问题在Hibernate 5.3及以上版本已经被官方修复了。建议你把Hibernate Core和Envers都升级到5.3.x的稳定版本(比如5.3.20.Final),同时搭配兼容的Hibernate Validator版本(比如6.1.x系列),确保所有Hibernate相关组件版本统一,避免版本冲突。
2. 自定义枚举类型(无法升级版本时的替代方案)
如果暂时不能升级Hibernate版本,可以自己实现一个自定义类型来处理枚举的字符串映射,让Envers能正确识别为CustomType:
实现自定义UserType
import org.hibernate.HibernateException; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.type.StringType; import org.hibernate.usertype.UserType; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Objects; public class EnumStringUserType<T extends Enum<T>> implements UserType { private Class<T> enumClass; // 初始化枚举类,可通过注解参数传入 public EnumStringUserType(Class<T> enumClass) { this.enumClass = enumClass; } @Override public int[] sqlTypes() { return new int[]{Types.VARCHAR}; } @Override public Class<T> returnedClass() { return enumClass; } @Override public boolean equals(Object x, Object y) throws HibernateException { return Objects.equals(x, y); } @Override public int hashCode(Object x) throws HibernateException { return Objects.hashCode(x); } @Override public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException { String value = StringType.INSTANCE.nullSafeGet(rs, names[0], session, owner); return value == null ? null : Enum.valueOf(enumClass, value); } @Override public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException { if (value == null) { st.setNull(index, Types.VARCHAR); } else { StringType.INSTANCE.nullSafeSet(st, ((Enum<?>) value).name(), 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 owner) throws HibernateException { return cached; } @Override public Object replace(Object original, Object target, Object owner) throws HibernateException { return original; } }
在实体类中使用自定义类型
import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; @Entity @Audited // 定义自定义类型,指定枚举类 @TypeDef(name = "yourEnumType", typeClass = EnumStringUserType.class, parameters = { @org.hibernate.annotations.Parameter(name = "enumClass", value = "com.yourpackage.YourEnum") }) public class YourEntity { @Type(type = "yourEnumType") private YourEnum yourEnum; // 其他字段和方法... }
3. 调整Glassfish类加载优先级
有时候Glassfish容器自带的Hibernate库和你应用打包的版本冲突,导致类加载异常。可以在glassfish-web.xml(Web应用)或者glassfish-application.xml(EAR应用)中配置类加载策略,让应用优先使用自身打包的库:
<glassfish-web-app> <class-loader delegate="false"/> </glassfish-web-app>
注意:修改类加载策略后,要确保应用打包的所有依赖都完整,避免容器提供的类缺失问题。
内容的提问来源于stack exchange,提问作者Rennan Lima
相关产品推荐
相关产品推荐

