2014-12-23 6 views
1

Таким образом, я создал базу данных, которая работала так:Почему MapDB не работает при повторном открытии базы данных?

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-миллиардные элементы, но как только я закрою ее и попробую снова открыть ее для большего чтения, она терпит неудачу.

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

ответ

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

    } 
Смежные вопросы