简体   繁体   English

审计:修改子实体的父实体(Javers / Envers /…+ Hibernate)

[英]Audit: Parent entity revision on child modification (Javers/Envers/… + Hibernate)

I have a kind of parent object in my application which needs to be versioned (audited), by that I mean: Every time an alteration on it is persisted, or on any of its n-deep child objects, a new revision must be created. 我的应用程序中有一个父对象,需要对它进行版本控制(审核),这意味着:每次对其或任何n个较深子对象进行持久化更改时,都必须创建一个新修订版本。 。

@Entity class Document {
    @Id String name;
    // some props ...
    @OneToMany List<Page> pages;
    // getters and setters ...
}

@Entity class Page {
    @Id Long number;
    @ManyToOne Document document;
    // some props ...
    String header;
    // getters and setters ...
}

In the example above, if I were to change the header of a page, a new revision should be persisted for the whole Document entity: 在上面的示例中,如果要更改页眉,则应为整个Document实体保留新的修订:

// retrieve document
Document document = documentRepository.findById(myBookId);
// change something on first found page
document.getPages().iterator().next().setHeader("Hello World");
// persist the document
documentRepository.save(document);
// new revision of the document!

I was considering using Javers or Envers but it seems none of them can do it. 我当时正在考虑使用JaversEnvers,但似乎他们都做不到。

Do any of you know how to do something like it on those libs? 你们中有人知道如何在这些库中执行类似的操作吗? Or know of any library I can use for this purpose? 还是知道我可以为此目的使用的任何库?

You can achieve it in Javers if you map Page class as ValueObject and then if you use Shadow query. 如果将Page类映射为ValueObject ,然后使用Shadow查询,则可以在Javers中实现。 Also you should commit Document all the time: 另外,您应该一直提交Document

    @Entity
    class Document {
        @Id String name
        @OneToMany List<Page> pages

        @Override
        String toString() {
            "Document $name, pages:$pages"
        }
    }

    @org.javers.core.metamodel.annotation.ValueObject
    @Entity
    @ToString
    class Page {
        @Id Long number
        @ManyToOne Document document
        String header

        @Override
        String toString() {
            "Page $number, $header"
        }
    }

    def "should treat Document as aggregate"(){
      given:
      def javers = JaversBuilder.javers().build()

      def doc = new Document(name:"1", pages: [new Page(header:"a"), new Page(header:"b")])
      javers.commit("author", doc)

      when:
      doc = new Document(name:"1", pages: [new Page(header:"a"), new Page(header:"ccc")])
      javers.commit("author", doc)

      def shadows = javers.findShadows(QueryBuilder.byClass(Document).build())

      then:
      shadows

      shadows.forEach{s -> println(s.commitMetadata.commitDate.toString() + " " + s.get())}
    }

output: 输出:

23:25:47.297 [main] INFO  org.javers.core.Javers - Commit(id:1.0, snapshots:3, author:author, changes - NewObject:3), done in 56 millis (diff:45, persist:11)
23:25:47.315 [main] INFO  org.javers.core.Javers - Commit(id:2.0, snapshots:1, author:author, changes - ValueChange:1), done in 17 millis (diff:17, persist:0)
23:25:47.337 [main] DEBUG org.javers.JQL - SHALLOW query: 4 snapshots loaded (entities: 1, valueObjects: 3)
23:25:47.358 [main] DEBUG org.javers.JQL - queryForShadows executed: 
2019-04-08T23:25:47.298618 Document 1, pages:[Page null, a, Page null, ccc]
2019-04-08T23:25:47.275570 Document 1, pages:[Page null, a, Page null, b]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM