Проблема с db4o (java) при выполнении запроса - PullRequest
0 голосов
/ 03 марта 2010

Я просматриваю части официального руководства по db4o и пытаюсь внести изменения в код, который они дают вам для выполнения собственных запросов:

//the original
List<Pilot> pilots = db.query(new Predicate<Pilot>() {
    public boolean match(Pilot pilot) {
        return pilot.getPoints() == 100;
    }
});

//modified
List<Pilot> pilots = db.query(new Predicate<Pilot>() {
    public boolean match(Pilot pilot) {
        return pilot.getGames() >= 100;
    }
});

Я добавил это в класс пилотов:

//in declarations
private ArrayList<String> games;  

//modified constructors
public Pilot() {
    this.name=null;
    this.points=0;
}
public Pilot(String name,int points) {
    this.name=name;
    this.points=points;
    this.games = new ArrayList<String>();
    int numGames = (int) (Math.random() * 1000 + 1);
    for(int i=0;i<numGames;i++) {
        this.games.add(name=" vs Computer");
    }
}

//new method
public int getGames() {
    return games.size();
}

Я уже заполнил базу данных 500 объектами, используя второй конструктор, и все данные в БД выглядят корректно с помощью дополнения OME eclipse. Я протестировал getGames (), и он работает как положено.

Моя проблема в том, что когда я запускаю измененный запрос, он возвращает все объекты в БД, и я не понимаю, почему. Я попытался изменить запрос, чтобы включить более стандартную, если это правда, иначе ложную структуру, и изменить запрос, чтобы включить требование определенного количества точек безрезультатно. Что бы я ни делал, кажется, он всегда оценивает (pilot.getGames ()> = 100) как истинное.

Может кто-нибудь помочь мне понять, почему?

1 Ответ

0 голосов
/ 04 марта 2010

Я думаю, вы нашли ошибку. db4o пытается перевести native-запросы в soda-запрос . Это позволяет избежать создания экземпляров объектов для выполнения запросов. Теперь вот этот перевод как-то не работает!

Когда вы выключаете оптимизацию, она работает. Вы можете сделать это через конфигурацию:

    EmbeddedConfiguration cfg = Db4oEmbedded.newConfiguration();
    cfg.common().optimizeNativeQueries(false);
    ObjectContainer db = Db4oEmbedded.openFile(cfg,DB_FILE)

Однако я не рекомендую это делать, потому что тогда все запросы будут выполняться медленно. Я нашел легкий обходной путь. Измените объявление поля games на List<String>. (И другие, будущие List-поля). Как это:

   class Pilot {
         private List<String> games;
         // rest
   }  

Это «деоптимизирует» собственный запрос, как только вы получите доступ к size () или другим методам, следовательно, избегает этой ошибки

Теперь «деоптимизированный» запрос может выполняться довольно медленно. Поэтому, если у вас много объектов и производительность неприемлема, я бы сделал это для этого запроса: создайте дополнительное поле, в котором будет храниться текущий размер списка Затем вы используете это дополнительное поле размера для этого типа запроса. Кроме того, вы можете затем индексировать поле размера.

Я сообщил об этом как об ошибке :

...