当前位置: 首页 > 知识库问答 >
问题:

Hibernate环境:@在子类上审核

锺离昂然
2023-03-14

我对实体Parent和Child有一个经典的继承持久性,其中Child扩展了Parent。类父级是抽象的,而子级不是抽象的。

我想审计孩子。此实体受我的控制,而父实体不受我的控制。此外,它还有许多不需要审计的子类。将整个层次结构上的继承策略连接起来。

因此,我用@Audited和@AuditOverride(forClass=Parent.class)注释了Child。

我得到的是以下错误:

org.hibernate.MappingException:实体“Child”已审核,但其超类“Parent”未审核

顺便说一下,我使用的是envers 4.0.1。最终版本。

有人知道我怎样才能做到这一点吗?我尝试过在子类中删除@Audited,删除@AuditOverride,在@Audited注释中使用不推荐的auditParents,但似乎没有任何效果。

这是父实体:

@Entity
@Table(name = "parent")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "type")
public class Parent {
    public Parent() {
        super();
    }

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "base_id", unique = true, nullable = false)
    private Integer baseId;

    @Column(name = "base_field")
    private String baseField;

    @Column(name = "type")
    private String type;

    // getters and setters
}

这是我的孩子实体:

@Entity
@Table(name = "child")
@DiscriminatorValue("CHILD")
@Audited
@AuditOverride(forClass = Parent.class)
public class Child extends Parent {
    public Child() {
        super();
    }

    @Column(name = "child_field")
    private String childField;

    // getters and setters
}

这些是实体:

CREATE  TABLE `REVINFO` (
  `REV` BIGINT NOT NULL AUTO_INCREMENT,
  `REVTSTMP` BIGINT NULL ,
  PRIMARY KEY (`REV`)
);

CREATE TABLE `parent` (
  `base_id` int(11) NOT NULL AUTO_INCREMENT,
  `base_field` varchar(45) DEFAULT NULL,
  `type` varchar(45) NOT NULL,
  PRIMARY KEY (`base_id`)
);

CREATE TABLE `child` (
  `base_id` int(11) NOT NULL AUTO_INCREMENT,
  `child_field` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`base_id`)
);

CREATE TABLE `child_AUD` (
  `base_id` int(11) NOT NULL,
  `REV` BIGINT NOT NULL,
  `REVTYPE` tinyint(2) DEFAULT NULL,
  `child_field` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`base_id`,`REV`)
);

这是一个测试用例:

public class EnversInheritanceTest extends AbstractJUnit4SpringContextTests {

    @Inject
    private EntityManagerFactory entityManagerFactory;

    private EntityManager entityManager;

    @Test
    public void inheritanceTest() {

        this.entityManager = this.entityManagerFactory.createEntityManager();

        Child child = this.createChild();
        this.saveChild(child);

        this.modifyChild(child);
        this.saveChild(child);

        Assert.assertNotNull(child.getBaseId());
        Assert.assertNotNull(this.getOriginalRevision(child.getBaseId()));

        Child original = this.getOriginalChild(child.getBaseId());

        Assert.assertNotNull(original);
        Assert.assertEquals("child", original.getChildField());

    }

    private Child createChild() {
        Child child = new Child();
        child.setBaseField("base");
        child.setChildField("child");
        child.setType("CHILD");
        return child;
    }

    private void saveChild(Child child) {
        this.entityManager.getTransaction().begin();
        this.entityManager.persist(child);
        // We need to commit in order to trigger Envers magic
        this.entityManager.getTransaction().commit();
    }

    private void modifyChild(Child child) {
        child.setBaseField("foo");
        child.setChildField("bar");
    }

    public Child getOriginalChild(Serializable id) {
        Object queryResult = this.getAuditReader().createQuery()
                .forEntitiesAtRevision(Child.class, this.getOriginalRevision(id))
                .add(AuditEntity.id().eq(id))
                .getSingleResult();
        return (Child) queryResult;
    }

    private Number getOriginalRevision(Serializable id) {
        AuditProjection minRevNumberAuditProjection = AuditEntity.revisionNumber().min();
        Number revision = (Number) this.getAuditReader().createQuery()
                .forRevisionsOfEntity(Child.class, false, false)
                .add(AuditEntity.id().eq(id))
                .addProjection(minRevNumberAuditProjection)
                .getSingleResult();

        return revision;
    }

    private AuditReader getAuditReader() {
        return AuditReaderFactory.get(this.entityManager);
    }

}

提前感谢您!

共有2个答案

薄兴昌
2023-03-14

尝试使用@Audited注释标记父类和子类,但对于父类添加@Audited(targetAuditMode=NOT\u Audited)

方俊
2023-03-14

一个很好的问题。2013年,jboss开发者论坛上也有同样的讨论。答案来自Hibernate Enver的创始人和项目负责人:

您必须以某种方式审计超类。目前除了注释之外,没有其他方法可以指定此类元数据。

在同一个讨论树中,根据父类也应该被注释的事实,建议在运行时对它们进行注释。但是这个决定看起来很难看,不适合您的情况:您可以手动注释父类。

作为一种解决方法,如果您不希望父类被审计,您可以尝试创建一个基本抽象MapdSuperClass,它本质上与父类相同,而父类只是它的后代,然后尝试将@AuditOverrid再次用于儿童类。它可能会“跳过”对P家长类的审计,而对儿童进行审计。

 类似资料:
  • 我正在编写一个模块来持久化一些数据,并使用OpenJPA作为持久化提供程序。但是现在我想给用户一个配置选项来在和之间切换。所以我写了一个新的DaoFactory类来创建,并在hibernate的中创建了新的持久性单元()。 现在,当我创建EntityManagerFactory时,问题出现了。我的密码是, 我的坚持。xml 我的Hibernate属性地图是, 这将选择OpneJPA作为正确的持久性

  • 我的项目中有几个类是由Hibernate处理的,有些是由Envers审核的,有些则不是。现在,当我试图保存某个未经审计的实体时,我得到了以下信息: 有些人可能认为我的数据库中没有审计表,但是Envers甚至不应该试图寻找这个表,因为实体没有被审计。我的类看起来像这样: 因此,每个类都包含一个子类列表,其中包含对其父类的引用。这些类都没有用-注释标记,但它们引用了一些已审核的实体。然而,每个引用都用

  • New in version 1.1. 你完全有可能遇到一些更新包需要通过proxy才能正常获取,或者甚至一部分包需要通过proxy升级而另外一部分包则不需要通过proxy.或者可能你的某个脚本需要调用某个环境变量才能正常运行. Ansible 使用 ‘environment’ 关键字对于环境部署的配置非常简单容易,下面是一个使用案例: - hosts: all remote_user: ro

  • 依照以下操作,你可在Mac,Linux(Debia/Ubuntu)上搭建PPMessage开发环境。 下载PPMessage源代码 首先需要安装git,然后从github下载源代码,假设保存路径为~/Documents/ppmessage。 git clone git@github.com:PPMESSAGE/ppmessage.git 安装依赖软件 进入~/Documents/ppmessage

  • 问题内容: 我对使用时如何搜索可执行文件感到困惑。如果给子进程提供了绝对路径,那么它就可以工作,但是我正在尝试使用相对路径。我发现,如果设置环境变量PYTHONPATH,则可以从该路径中获取导入的模块,并且PYTHONPATH在其中,但似乎对的行为没有帮助。我也尝试编辑将PYTHONPATH添加到的文件,就像这样 并验证了在以交互方式,与ipython或通过从命令行运行脚本启动python时,PY