2010-03-03 17 views
0

je en regardant à travers des parties du official db4o tutorial, et je suis en train de faire une modification du code qu'ils vous donnent pour les requêtes en natif:problème avec db4o (java) lors de l'exécution d'une requête

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

Je l'ai ajouté à leur classe pilote:

//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(); 
} 

Je l'ai déjà peuplé une base de données avec 500 objets en utilisant le second constructeur, et toutes les données dans la db semble correct avec l'addon éclipse OME. J'ai testé getGames() et cela fonctionne comme prévu.

Mon problème est que lorsque j'exécute la requête modifiée, elle renvoie tous les objets dans la base de données et je ne comprends pas pourquoi. J'ai essayé de changer la requête pour inclure un plus standard si vrai, sinon la structure fausse et changeant la requête pour inclure exigeant un certain nombre de points en vain. Quoi que je fasse, il semble qu'il évalue toujours (pilot.getGames()> = 100) pour être vrai.

Quelqu'un peut-il m'aider à comprendre pourquoi?

Répondre

0

Je pense que vous avez trouvé un bug. db4o essaie de traduire le native-queries into a soda-query. Cela évite d'instancier des objets pour effectuer des requêtes. Maintenant, cette traduction ne fonctionne pas!

Lorsque vous désactivez l'optimisation, cela fonctionne. Vous pouvez le faire via la configuration:

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

Cependant, je ne le recommande pas car toutes les requêtes seront alors lancées lentement. J'ai trouvé une solution de contournement facile. Changez la déclaration du champ games en List<String>. (Et d'autres, futurs champs de liste). Comme ceci:

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

Ce sera « deoptimize » une requête native dès que vous accédez à la taille() ou d'autres méthodes, évite donc ce bug.

Maintenant, une requête 'deoptimized' peut être assez lente. Donc, si vous avez beaucoup d'objets et que les performances sont inacceptables, je le ferais pour cette requête: Créez un champ supplémentaire qui stocke la taille actuelle de la liste. Ensuite, vous utilisez ce champ de taille supplémentaire pour ce type de requête. De plus, vous pouvez ensuite indexer le champ de taille.

J'ai rapporté this as a bug:

+0

Merci beaucoup, monsieur! – fusion2004