javers - Javers ~ 查询仓库的当前状态
问题描述
这听起来很基本,应该很容易,但不知何故我不知道该怎么做。
使用 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'
}
解决方案
我现在编写了一个实用程序类,它利用阴影从最新到最旧排序这一事实,以最少的麻烦解决这个问题:
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 字段的对象都可以毕竟分组在一个抽象类中),所以这对我来说并不是最优的。
因此,如果有人有更好的解决方案,请随时在此处发布。在此之前,我仍会保留此解决方法,因为它可以完成工作。
推荐阅读
- java - 如何在课堂上存储 Arraylist?
- swift - iPad Pro - 限制到底部不起作用 - 随机底部栏
- python - 为什么 Keras 训练一段时间后会变慢?
- amazon-web-services - AWS 文档:如何在 API Gateway 中使用 Lambda 的响应变量?
- java - 我用java写了一些代码。我只是使用了 if-else、函数和递归方法。我怎样才能做得更好?
- html-helper - ADNStoreFront Multistore AddtoCartForm 功能崩溃页面
- javascript - 当我将元素拖放到图像上时,如何使图像不可见?
- c# - MigrationBuilder:InsertData 并取回 ID
- powershell - 将新的 VMware 服务器从模板部署到具有不同存储策略的集群
- mysql - 由参数 SQL 定义的 Select 语句