我浏览了official db4o tutorial的一部分,并试图对它们提供的用于运行原生查询的代码进行修改:
//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;
}
});我将这个添加到他们的Pilot类中:
//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(),它可以像预期的那样工作。
我的问题是,当我运行修改后的查询时,它返回数据库中的所有对象,我不知道为什么。我尝试将查询更改为包含更标准的if true,else false结构,并将查询更改为包含需要一定数量的点数,但均无济于事。无论我做什么,似乎总是计算(pilot.getGames() >= 100)为真。
有人能帮我理解为什么吗?
发布于 2010-03-04 05:23:39
我想你发现了一个bug。db4o尝试转换native-queries into a soda-query。这避免了实例化对象来执行查询。现在,这个翻译不知何故不起作用了!
当您关闭优化时,它会起作用。您可以通过以下配置完成此操作:
EmbeddedConfiguration cfg = Db4oEmbedded.newConfiguration();
cfg.common().optimizeNativeQueries(false);
ObjectContainer db = Db4oEmbedded.openFile(cfg,DB_FILE)但是,我不建议这样做,因为这样所有的查询都会运行缓慢。我找到了一个简单的解决方法。将games-field的声明更改为List<String>。(以及其他未来的列表字段)。如下所示:
class Pilot {
private List<String> games;
// rest
} 这将在您访问size()或其他方法时立即“取消优化”原生查询,从而避免了此错误。
现在,“去优化”的查询可能会运行得相当慢。所以,如果你有很多对象,而且性能是不可接受的,我会对这个查询这样做:创建一个额外的字段,用来存储列表的当前大小。然后,对这种查询使用这个额外的size-field。此外,您还可以为size-field建立索引。
我已经报告了this as a bug
https://stackoverflow.com/questions/2373911
复制相似问题