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

Javer不为集合内对象属性的更改创建快照

喻选
2023-03-14

我正在评估javers,以便将其用于审计实体。我有一个嵌套的ValueObject集合的实体。我希望值对象上的每个属性更改都会生成实体的快照。只有在将值对象添加到集合中时才会创建快照。在我的例子中,我向集合添加了两个值对象,创建了实体的两个快照。第三次,我只是改变了value对象的一个属性,javers没有意识到这是对实体的改变,而是为内部value对象创建了一个快照。

我的问题是我的假设是否有效,或者跟踪集合中值对象的更改的最佳方法是什么

下面是我使用Spring引导创建的一个简单测试的代码。

我使用的是Javers3.2版。0

我的实体如下

package com.example.javersdemo;

import com.fasterxml.jackson.annotation.JsonUnwrapped;
import lombok.Data;
import org.javers.core.metamodel.annotation.TypeName;

import javax.persistence.CollectionTable;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import java.util.List;

@Data
@Entity
@TypeName("User")
class User{
    @Id
    private String name ;


    @JsonUnwrapped
    @ElementCollection(targetClass = Hobby.class)
    @CollectionTable(name = "USER_HOBBIES")
    @JoinColumn(name = "NAME")
    private List<Hobby> hobbies;

    private User(){

    }

    public User(String name, List<Hobby> hobbies) {
        this.name = name;
        this.hobbies = hobbies;
    }
}

值对象如下所示

package com.example.javersdemo;

import lombok.Data;

import javax.persistence.Embeddable;

@Data
@Embeddable
public class Hobby {

    private String hobby;

    private boolean active;

    private Hobby() {

    }

    public Hobby(String hobby, boolean active) {

        this.hobby = hobby;
        this.active = active;
    }
}

我的spring数据存储库如下

package com.example.javersdemo;

import org.javers.spring.annotation.JaversSpringDataAuditable;
import org.springframework.data.repository.CrudRepository;


@JaversSpringDataAuditable
interface TestUserRepository extends CrudRepository<User,String> {

}

下面是我创建的一个spock集成测试,用于验证集合中对象属性的更改是否会创建一个新快照。

package com.example.javersdemo

import org.javers.core.Javers
import org.javers.repository.jql.QueryBuilder
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import spock.lang.Specification

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class JaversInnerValueObjectsTest extends Specification {

    @Autowired
    TestUserRepository userRepository

    @Autowired
    Javers javers


    def 'should create 6 snapshots'() {

        given:
        def hobbies = [new Hobby('Reading books', true)]
        def user = new User('John', hobbies)

        when:
        userRepository.save(user)

        hobbies = [new Hobby('Reading books', true), new Hobby('Watching Soccer', true)]

        user.hobbies = hobbies

        userRepository.save(user)

        hobbies = [new Hobby('Reading books', true), new Hobby('Watching Soccer', false)]

        user.hobbies = hobbies

        userRepository.save(user)



        then:
        QueryBuilder jqlQuery = QueryBuilder.byInstanceId('John', User)
        def snapshots = javers.findSnapshots(jqlQuery.withChildValueObjects().build())
        snapshots.size() == 6


    }

}

测试失败,错误如下

不满足条件:

快照。size()=6 | | | | 5 false[快照{commit:3.0,id:User/John#嗜好/1,版本2,(嗜好:观看足球)},快照{commit:2.0,id:User/John#嗜好/1,版本1,(active:true,嗜好:观看足球)},快照{commit:2.0,id:User/John John,版本2,(嗜好:[User/John嗜好/John#嗜好/0,User/John嗜好/1],name:John,快照{commit:1.0,id:User/John#嗜好/0,版本:1,(活动:true,嗜好:阅读书籍)},快照{commit:1.0,id:User/John,版本:1,(嗜好:[User/John#嗜好/0],姓名:John)}]

预期: 6

实际:5

共有1个答案

沈自珍
2023-03-14

日志中有JaVers提交统计信息:

13:27:44.315 [main] INFO  org.javers.core.Javers - Commit(id:1.0, snapshots:2, author:author, changes - NewObject:2), done in 71 millis (diff:71, persist:0)
13:27:44.333 [main] INFO  org.javers.core.Javers - Commit(id:2.0, snapshots:2, author:author, changes - ListChange:1 NewObject:1), done in 17 millis (diff:17, persist:0)
13:27:44.336 [main] INFO  org.javers.core.Javers - Commit(id:3.0, snapshots:1, author:author, changes - ValueChange:1), done in 3 millis (diff:3, persist:0)

在firts提交中,创建了两个快照,因为这里有两个新对象。

在第二次提交中,将创建另外两个快照:

  • 用户(实体)快照,因为用户的字段<代码>爱好 已更改-新项目已添加到列表中,因此列表更改

在第三次提交中,只创建了1个快照,因为用户的字段爱好不会更改。JaVers将值对象集合和实体集合视为引用集合(GlobalId's)。在这种情况下,引用不会更改。集合的状态捕获如下:

["User/John#hobbies/0",
 "User/John#hobbies/1"]

第三次提交中唯一的变化是爱好的字段变化(true)-

换句话说,当您更改某个实体拥有的值对象,并且实体状态没有更改时,将不会创建实体快照,因为它与前一个快照完全相同。

 类似资料:
  • 我想使用JaVers来跟踪我的Java对象的更改。基本示例工作正常,但我无法让它检测存储在集合中的对象的更改。 如果我扩展ChangeLogExample。更改例如其中一个子坐标的课堂示例: 这是打印的更改日志: 因此,第一个下属的年龄变化不会显示在变更日志中。 使用withChildValueObjects()没有什么不同。 当我单独将更改提交给员工实例时,我会得到学员年龄的更改,但这不是我想要

  • pageScope、requestScope、sessionScope和applicationScope四个EL内置对象分别对应page、request、session和application四个域的属性集合。这四个EL内置对象可以使用如下两种方法访问域属性集合中的对象: 1. 获得特定域属性集合中的对象:这种方法需要指定要获得哪个域的属性。如下面的代码将获得request域中的name属性: $

  • 出于业务逻辑的原因,我希望能够创建一个具有属性的对象。但我显然不能 因为是在Python中具有特殊含义的保留关键字。但是,使用或动态获取属性也存在同样的问题。我可以这样做吗,还是必须让属性名?

  • 问题内容: 用Javascript将是: 但是Python中相同的语法会创建一个字典,那不是我想要的 问题答案: 有两种功能用途。

  • 我有以下Java超类,每个属性都有构造函数、getter和setter: 和一个car子类,它扩展了vehicle超类,并具有几个独特的属性: 我创建一个新的vehicle对象链表,并向其中添加一个新的car对象: 我可以用下面这样的函数更改属于vehicle超级类的任何属性: 但是当我试图创建一个类似的函数来更改其中一个子类属性时,我得到了这个错误:“方法setWheels(int)对于类型Ve

  • 我正在制作Spring云流Kafka流活页夹。在我的consumerbean方法中,我希望返回KStream,并将字符串列表作为值- 是否可以使用集合作为其值的KStream?如果是,有人能解释一下如何创建它吗?