我发现有许多实体类使用相同的主键 id 类型。
例如,
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
//...
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
秉承 DRY(不要重复自己)的原则,我认为将其变成一个通用的抽象父类供所有子类使用是有意义的(在某种程度上确实如此)。
@MappedSuperclass
public abstract class LongIdEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
public LongIdEntity() {}
public LongIdEntity(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
}
当我尝试将这个抽象父类与也用 @org.hibernate.envers.Audited 注释的子类一起使用时,我的问题出现了。
由于某种原因,当任何子类使用 @org.hibernate.envers.Audited 映射并扩展 LongIdEntity 时,Hibernate 会抛出以下错误。
ERROR 63328 --- [persistence] [ main] o.h.metamodel.internal.MetadataContext : HHH015007: Illegal argument on static metamodel field injection : org.hibernate.envers.DefaultRevisionEntity_#class_; expected type : org.hibernate.metamodel.model.domain.internal.EntityTypeImpl; encountered type : jakarta.persistence.metamodel.MappedSuperclassType
现在我已经尝试了很多事情,但在深入研究任何尝试之前,我想指出,即使出现错误,Hibernate 仍然按照最初的预期构造表(即子类获得自己唯一的 id 列,即经过审计,代码的语法显着减少,因为我们只需要在整个应用程序中声明一次 Long id,并且可以根据需要重用它)。
至于我尝试过的尝试,
用 @Audited 注释父类和子类 - 这引发了相同的错误
仅使用 @Audited 注释子类 - 这是我当前使用的设置,尽管出现错误消息,但仍会导致功能性休眠。
仅注释不执行任何操作的超类(这是故意的),因为父类字段继承到子类中,就好像它们是自己的列一样,导致父类没有自己的表,并且扩展后没有正在接受审核。此外,错误消失了,考虑到错误状态 hibernate 需要实体类型并获得映射的超类类型,并且这两个注释同时应用于同一个父类,这有点奇怪。
我可以保持原样,但我担心这些事情,因为即使它现在在技术上可以工作,这可能会在未来导致一些意想不到的后果/错误。
我在 Quarkus 框架和 Quarkus Hibernate Envers 扩展方面至少遇到一个问题。
HHH015007: Illegal argument on static metamodel field injection : org.hibernate.envers.DefaultRevisionEntity_#class_; expected type : org.hibernate.metamodel.model.domain.internal.EntityTypeImpl; encountered type : jakarta.persistence.metamodel.MappedSuperclassType
它将在 Hibernate 7.0 中根据 HHH-17612
进行修复