Почему не работает MapDB при повторном открытии базы данных?

1

Поэтому я создал базу данных, которая работала следующим образом:

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]);

    }

}

После того как я создал его, я вставил 19 миллиардов предметов. Методы достижения всех записей с помощью какого-либо действия или человека работали отлично. Я закрыл базу данных, а затем попробовал запустить ее снова, за исключением того, что база данных уже была построена, и все элементы вставлены, поэтому нет необходимости вставлять 19 миллиардов элементов. Как только я назвал один из методов для достижения всех записей с каким-то действием или человеком, я получаю эту ошибку:

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 *, "что-то"), но действие его вызова не делает его неудачным, просто пытаясь перебирать его. Я протестировал его так:

//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");

Итак, теперь я застрял, и я понятия не имею, что случилось с моей картой. Он отлично работает, когда я создал новую БД и вставил 19-миллиардные элементы, но как только я закрою ее и попробую снова открыть ее для большего чтения, она терпит неудачу.

Может ли кто-нибудь помочь? Благодарю.

Теги:
mapdb

1 ответ

3

Я нашел решение, оно включает объединение map_commonPerson и map_commonAction в одну и ту же карту и использование Bind.secondaryKeys() вместо функции Bind.secondaryKey(). Почему это? Может ли быть только один исполнитель изменений, установленный на карту?

Вот код для рабочей БД, который правильно восстановился после закрытия:

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]);

    }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню