添加static final自定义字段后Hibernate无法加载Channel实体类
问题描述
在Hibernate实体类Channel中添加static final类型的自定义VarType字段(ID和TITLE)后,出现无法加载Channel类的错误,移除这些字段后程序运行正常。相关代码及报错信息如下:
实体类Channel代码
@Entity @Table(name = "channels") public class Channel { public static final VarType ID = new VarType(Channel.class, "id", Integer.class); public static final VarType TITLE = new VarType(Channel.class, "title", String.class); @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column(name = "chatid") private long chatId; // 省略其他代码 }
自定义VarType类代码
public class VarType { Class<?> cls; String name; Class<?> type; public VarType(Class<?> cls, String name, Class<?> type) { this.cls = cls; this.name = name; this.type = type; } // 省略其他代码 }
报错信息
Caused by: org.hibernate.MappingException: entity class not found: com.saderty.db.entities.Channel at org.hibernate.mapping.PersistentClass.getMappedClass(PersistentClass.java:144) ... Caused by: java.lang.ExceptionInInitializerError at java.base/java.lang.Class.forName0(Native Method) ...
Hibernate配置代码
Configuration configuration = new Configuration(); configuration.addAnnotatedClass(annotatedClass); new HibernateApi(configuration);
问题根源
问题出在类初始化顺序上:
JVM加载Channel类时,会优先初始化static字段。此时执行new VarType(Channel.class, ...)时,Channel类本身还未完成初始化流程(类加载分为加载、链接、初始化三个阶段,此时正处于初始化阶段),这种情况下尝试引用Channel.class会触发初始化异常,抛出ExceptionInInitializerError,最终导致Channel类加载失败,Hibernate自然找不到这个实体类。
解决方案
将static final字段的初始化延迟到Channel类完成初始化之后,最直接的方式是使用静态代码块来初始化这些字段:
@Entity @Table(name = "channels") public class Channel { public static final VarType ID; public static final VarType TITLE; // 静态代码块会在类初始化的最后阶段执行 static { ID = new VarType(Channel.class, "id", Integer.class); TITLE = new VarType(Channel.class, "title", String.class); } @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column(name = "chatid") private long chatId; // 省略其他代码 }
这样修改后,Channel类会先完成自身的初始化(包括实体字段、注解等的处理),再执行静态代码块初始化VarType实例,避免了类初始化阶段的依赖问题,Hibernate就能正常加载Channel类了。
内容的提问来源于stack exchange,提问作者Saderty
相关产品推荐
相关产品推荐

