gpt4 book ai didi

java - 为什么重新打开数据库时 MapDB 不工作?

转载 作者:行者123 更新时间:2023-11-29 05:13:01 28 4
gpt4 key购买 nike

所以我创建了一个像这样工作的数据库:

static class Record implements Serializable
{
final String action;
final String categoryOfAction;
final String personWhoPerformedAction;
final Long timeOfOccurrence;

public record(String actn, String cat, String person, Long time)
{
action = actn;
categoryOfAction = cat;
personWhoPerformedAction = person;
timeOfOccurence = time;
}

}

static void main(String[] args)
{
DB thedb = DBMaker.newFileDB(new File("D:\\thedb.db")
.compressionEnable()
.closeOnJvmShutdown()
.mmapFileEnableIfSupported()
.transactionDisable()
.asyncWriteEnable()
.make();

//primaryMap maps each record to a unique ID
BTreeMap<Integer,Record> primaryMap = thedb.createTreeMap("pri")
.keySerializer(BTreeKeySerializer.INTEGER)
.makeOrGet();;

//this map holds the unique ID of every record in primaryMap with a common action
NavigableSet<Object[]> map_commonAction = thedb.createTreeSet("com_a")
.comparator(Fun.COMPARABLE_ARRAY_COMPARATOR)
.makeOrGet();

//this map holds the unique ID of every record in primaryMap with a common person
NavigableSet<Object[]> map_commonPerson = thedb.createTreeSet("com_p")
.comparator(Fun.COMPARABLE_ARRAY_COMPARATOR)
.makeOrGet();

//binding map_commonAction to primaryMap so it is updated with primary
Bind.secondaryKey(primaryMap, map_commonAction, new Fun.Function2<String, Integer, Record>() {
@Override
public String run(Integer recordID, Record r) {
return r.action;
}
});

//binding map_commonPerson to primaryMap so it is updated with primary
Bind.secondaryKey(primaryMap, map_commonPerson, new Fun.Function2<String, Integer, Record>() {
@Override
public String run(Integer recordID, Record r) {
return r.personWhoPerformedAction;
}
});


//method used to attain all records with some action
for (Object[] k : Fun.filter(map_commonAction, "someAction"))
{
Record obtainedRecord = primary.get(k[1]);

}

//method used to attain all records with some person
for (Object[] k : Fun.filter(map_commonPerson, "somePerson"))
{
Record obtainedRecord = primary.get(k[1]);

}

}

我创建后,插入了 190 亿项。通过某些 Action 或人获得所有记录的方法非常有效。我关闭了数据库,然后我尝试再次运行它,只是这次数据库已经建立并且已经插入了所有项目,所以不需要插入 190 亿个项目。一旦我调用了一种方法来通过某些操作或人员获得所有记录,我收到此错误:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to java.lang.Comparable
at org.mapdb.Fun$1.compare(Fun.java:31)
at org.mapdb.BTreeKeySerializer$BasicKeySerializer.compare(BTreeKeySerializer.java:206)
at org.mapdb.BTreeKeySerializer$BasicKeySerializer.compare(BTreeKeySerializer.java:156)
at org.mapdb.BTreeKeySerializer.compareIsSmaller(BTreeKeySerializer.java:48)
at org.mapdb.BTreeKeySerializer.findChildren(BTreeKeySerializer.java:89)
at org.mapdb.BTreeMap.nextDir(BTreeMap.java:843)
at org.mapdb.BTreeMap.findLargerNode(BTreeMap.java:1673)
at org.mapdb.BTreeMap$BTreeIterator.<init>(BTreeMap.java:1068)
at org.mapdb.BTreeMap$BTreeKeyIterator.<init>(BTreeMap.java:1323)
at org.mapdb.BTreeMap$SubMap.keyIterator(BTreeMap.java:2483)
at org.mapdb.BTreeMap$KeySet.iterator(BTreeMap.java:1900)
at org.mapdb.Fun$12.iterator(Fun.java:369)
at test.main(test.java:187)

于是接着查看每张图的大小

    System.out.println(map_commonAction.size()); //returned correct size: 19billion
System.out.println(map_commonPerson.size()); //returned correct size: 19billion
System.out.println(primaryMap.size()); //returned correct size: 19billion

然后我检查了 primaryMap 是否有效,并检查了几个 int 值,它返回了一条应该有的记录

    Record r1 = primaryMap.get(1);
Record r2 = primaryMap.get(2);

System.out.println(r1.toString());
System.out.println(r2.toString());

只有当我尝试遍历 Fun.filter(map_common*, "something") 给出的内容时才会失败,但调用它的行为不会使其失败,只是试图遍历它。我是这样测试的:

//this method fails and causes and exception to be thrown
for (Object[] k : Fun.filter(map_commonPerson, "person"))
{
System.out.println(primaryMap.get(k[1]).toString());
}

//this method doesn't cause an exception to be thrown
Iterable<Object[]> x = Fun.filter(map_commonPerson, "person");

所以现在我卡住了,我不知道我的 map 出了什么问题。一旦我创建了一个新的数据库并插入了 190 亿个项目,它就完美地工作了,但是一旦我关闭它并尝试重新打开它以进行更多阅读,它就会失败。

有人可以帮忙吗?谢谢。

最佳答案

我找到了一个解决方案,它涉及将 map_commonPerson 和 map_commonAction 组合到同一个 map 中,并使用 Bind.secondaryKeys() 而不是 Bind.secondaryKey() 函数。为什么是这样?每个 map 只能安装一个修改监听器吗?

这是关闭后正确恢复的工作数据库的代码:

static class Record implements Serializable
{
final String action;
final String categoryOfAction;
final String personWhoPerformedAction;
final Long timeOfOccurrence;

public record(String actn, String cat, String person, Long time)
{
action = actn;
categoryOfAction = cat;
personWhoPerformedAction = person;
timeOfOccurence = time;
}

}

static void main(String[] args)
{
DB thedb = DBMaker.newFileDB(new File("D:\\thedb.db")
.compressionEnable()
.closeOnJvmShutdown()
.mmapFileEnableIfSupported()
.transactionDisable()
.asyncWriteEnable()
.make();

//primaryMap maps each record to a unique ID
BTreeMap<Integer,Record> primaryMap = thedb.createTreeMap("pri")
.keySerializer(BTreeKeySerializer.INTEGER)
.makeOrGet();;

//this map holds the unique ID of every record with the same person or action
NavigableSet<Object[]> map_commonAttributes = thedb.createTreeSet("com_a")
.comparator(Fun.COMPARABLE_ARRAY_COMPARATOR)
.makeOrGet();

//binding map_commonAction to primaryMap so it is updated with primary
Bind.secondaryKeys(primaryMap, map_commonAttributes, new Fun.Function2<String[], Integer, Record>() {
@Override
public String[] run(Integer recordID, Record r) {
return new String[]{record.action, record.personWhoPerformedAction};
}
});


//method used to attain all records with same person or action
for (Object[] k : Fun.filter(map_commonAttribute, "somePersonOrAction"))
{
Record obtainedRecord = primary.get(k[1]);

}

关于java - 为什么重新打开数据库时 MapDB 不工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27628709/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com