【问题标题】:Javers ~ Querying the Current State of the repositoryJavers ~ 查询仓库的当前状态
【发布时间】:2020-10-09 12:36:10
【问题描述】:

这听起来很简单,应该很容易,但不知怎么做,我不知道该怎么做。

使用 Javers,如何获取存储库的当前状态?

示例:我有三个字符,其中一个字符得到更新。现在我想查询当前所有字符的列表:

public class JaversMemoryRepositoryTest {
    private static final String AUTHOR_NAME = "Luther Lansfeld";
    private static Javers javersRepository;
    GameCharacter sylvia;
    GameCharacter bokay;
    GameCharacter cyrus;
    
    @BeforeEach
    public void setUpJaversRepository() {
        javersRepository = JaversBuilder.javers().build();
        sylvia = GameCharacters.sylvia();
        javersRepository.commit(AUTHOR_NAME, sylvia);
        sylvia.name = "Sylvia the Atomic";
        javersRepository.commit(AUTHOR_NAME, sylvia);
        bokay= GameCharacters.bokay();
        javersRepository.commit(AUTHOR_NAME, bokay);
        cyrus= GameCharacters.cyrus();
        javersRepository.commit(AUTHOR_NAME, cyrus);
    }

    @Test
    public void queryShouldFindLatestVersionOfEachCharacter() {
        JqlQuery entryQuery = QueryBuilder.byClass(GameCharacter.class).build();
        List<Shadow<GameCharacter>> gameCharacterShadowList
            = javersRepository.findShadows(entryQuery);
        assertEquals(3, gameCharacterShadowList.size());
    }
}

但是,该测试失败(得到 4,预期为 3),因为我得到了 Sylvia 的两个阴影。

我知道我可能可以通过一个遍历阴影的函数来解决这个问题,通过 ID 将它们分开,并只留下最新版本的那个,但不知何故,对于我确定的如此基本的东西来说,这感觉有点矫枉过正Javers 应该在某个地方拥有它。

大概是这样的:

JqlQuery entryQuery = QueryBuilder.byClass(GameCharacter.class).withLatestVersion().build();

...除了这不存在。但这是关于我在这里尝试做的事情。

或相反:

JqlQuery entryQuery = QueryBuilder.byClass(GameCharacter.class).withVersion(1).build();

...获取每个 GameCharacter 的最旧版本。我已经为此尝试过withVersion(-1),但显然 Javers 并没有从最后开始计算版本。

对此的任何反馈将不胜感激。

编辑:这是一个测试用例,由于未实现预期的行为,当前崩溃,但可以很好地复制用例:

import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.*;

import java.util.*;

import org.javers.core.*;
import org.javers.core.metamodel.annotation.Id;
import org.javers.repository.jql.*;
import org.javers.shadow.Shadow;
import org.junit.jupiter.api.*;

public class GetLatestVersionTest {
    private static final String FIRST_STRING = "This string should be in the end result";
    private static final String SECOND_STRING = "This string will get overwritten with a newer version";
    private static final String THIRD_STRING = "This string should also be in the end result";
    private static final String FOURTH_STRING = "This string should be in the end result as well";
    private static final String AUTHOR_NAME = "Test Author";

    @Test
    public void shouldRetrieveOnlyLatestVersionsOfAllObjects() {
        Javers javers = JaversBuilder.javers().build();
        StringContainer firstObject = new StringContainer(FIRST_STRING);
        javers.commit(AUTHOR_NAME, firstObject);
        StringContainer secondObject = new StringContainer(SECOND_STRING);
        javers.commit(AUTHOR_NAME, secondObject);
        StringContainer thirdObject = new StringContainer(THIRD_STRING);
        javers.commit(AUTHOR_NAME, thirdObject);
        secondObject.string = FOURTH_STRING;
        javers.commit(AUTHOR_NAME, secondObject);
        
        //At this point, some logic is needed that will only query the latest version
        JqlQuery entryQuery = QueryBuilder.byClass(StringContainer.class).withVersion(-1).build();
        List<Shadow<StringContainer>> mostRecentShadows = javers.findShadows(entryQuery);
        
        assertEquals(3, mostRecentShadows.size());
        List<String> mostRecentStrings = new ArrayList<>();
        for(Shadow<StringContainer> shadow : mostRecentShadows) {
            mostRecentStrings.add(shadow.get().string);
        }
        assertTrue(mostRecentStrings.contains(FIRST_STRING));
        assertFalse(mostRecentStrings.contains(SECOND_STRING));
        assertTrue(mostRecentStrings.contains(THIRD_STRING));
        assertTrue(mostRecentStrings.contains(FOURTH_STRING));
    }
}

class StringContainer {
    @Id
    public String string;
    
    public StringContainer(String string) {
        this.string = string;
    }
}

Gradle 依赖项是:

plugins {
    id 'java-library-distribution'
}

repositories {
    jcenter()
}

dependencies {
    // Use JUnit test framework
    testCompile("org.junit.jupiter:junit-jupiter:5.6.0")
    testCompile("org.junit.platform:junit-platform-runner:1.6.0")
    
    //Logging
    compile 'commons-logging:commons-logging:1.2'
    compile 'log4j:log4j:1.2.17'
    compile 'org.slf4j:slf4j-log4j12:1.7.25'
    compile 'commons-logging:commons-logging:1.2'
    
    //JaVers
    compile 'org.javers:javers-core:5.10.0'
    compile 'org.javers:javers-persistence-mongo:5.10.0'
}

【问题讨论】:

  • 嗨,如果你想让我看看你的问题,请推送一个可运行的测试用例,例如github.com/javers/javers/tree/master/javers-core/src/test/…
  • @BartekWalacik :我已经准备了一个测试文件,该文件至少在我自己的项目中本地工作,如果我知道如何将它推送到存储库,我很乐意。我尝试在本地创建一个新分支并将其推送到 github,但不知何故它没有出现。我也尝试将文件直接上传到 github,但 github 说我不允许这样做,因为推送访问被禁用。无论如何,我会将文件添加为上面的编辑,因此您可以复制它。感谢您的辛勤劳动。 =^,^=

标签: javers


【解决方案1】:

我现在编写了一个实用程序类,它利用阴影按最新到最旧排序这一事实,以最少的麻烦解决这个问题:

    public static List<Shadow<GameCharacter>> getLatestShadowsFrom(
        List<Shadow<GameCharacter>> gameCharacterShadowList
    ) {
        List<Shadow<GameCharacter>> latestGameCharacterShadows
            = new ArrayList<>();
        List<String> registeredGameCharacterShadowIds
            = new ArrayList<>(); 
        for(Shadow<GameCharacter> gameCharacterShadow : gameCharacterShadowList) {
            String gameCharacterId
                = gameCharacterShadow.get()._id;
            if(!registeredGameCharacterShadowIds.contains(gameCharacterId)) {
                registeredGameCharacterShadowIds.add(gameCharacterId);
                latestGameCharacterShadows.add(gameCharacterShadow);
            }
        }
        return latestGameCharacterShadows;
    }

这样应用:

    @Test
    public void queryShouldFindLatestVersionOfEachCharacter() {
        JqlQuery entryQuery = QueryBuilder.byClass(GameCharacter.class).build();
        List<Shadow<GameCharacter>> allGameCharacterShadows
            = javersRepository.findShadows(entryQuery);
        List<Shadow<GameCharacter>> latestGameCharacterShadows
            = JaversUtilities.getLatestShadowsFrom(allGameCharacterShadows);
        assertEquals(3, latestGameCharacterShadows.size());
    }

然而,这种方法的主要缺点是,因为这个函数依赖于 GameCharacter 的 _id 字段,所以我必须为每个具有不同 ID 变量的对象(所有那些具有 _id毕竟可以将字段分组到一个抽象类中),所以这对我来说并不是最优的。

所以,如果有人有更好的解决方案,请随时在此处发布。在此之前,我仍会保留此解决方法,因为它可以完成工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 2021-10-02
    • 1970-01-01
    • 2019-07-09
    相关资源
    最近更新 更多