SODA Query API
SODA是db4o底层查询接口,它允许你直接使用查询图的节点。由于SODA使用字符串来区分属性,所以没有很好类型安全
机制和编译时检测,同时,它的书写比较冗长。对于大多数应用,NQ是比较好的查询接口。然而,如果一个应用需要动态生成查询条件的需求,SODA将是必须的,这就是为什么在这介绍它。
简单的查询:
让我们看看如何将我们熟悉的QBE查询条件用SODA来表示,一个新的查询对象通过query()方法从ObjectContainer中得到,
我们可以给它添加约束条件。查询所有Pilot实例,我们通过Pilot来添加约束。
QueryExample.java: retrieveAllPilots
public static void retrieveAllPilots() {
ObjectContainer db=Db4o.openFile(YAPFILENAME);
try {
Query query=db.query();
query.constrain(Pilot.class);
ObjectSet result=query.execute();
listResult(result);
} finally {
db.close();
}
}
基本上,我们交换我们真实的原形来用元数据来表述我们想要查找的对象:一个查询图是由查询节点和约束组成。查询节点
对于候选对象而言是一个占位符,而约束条件决定是否要添加或者去除候选对象。
我们简单的查询图如下:
图一
我们仅仅查询任意候选对象(在这里,也就是数据库中所有对象)它们的类型是Pilot将并加入结果集中。
通过pilot的名字来查询,我们不得不进一步通过名字属性和字符串的值来限制候选对象。
public static void retrievePilotByName(ObjectContainer db) {
Query query=db.query();
query.constrain(Pilot.class);
query.descend("name").constrain("Michael Schumacher");
ObjectSet result=query.execute();
listResult(result);
}
在这里,decend意思是什么呢?其实正如我们真实原形,我们添加约束条件来约束我们候选中的子成员.
图二
所以,一个候选者是pilot类型,有一个"name"属性,并且值等于所给的字符串.
注意:对于类型的约束不是必须的,如果你去除,查询结果将是所有具有"name"属性.并且值等于所给的所有对象,但是这种查询不符合一般的查询行为.通过精确条件查找一个pilot是类似的,我们通过java原始对象区别.
QueryExample.java: retrievePilotByExactPoints
public static void retrievePilotByExactPoints(
ObjectContainer db) {
Query query=db.query();
query.constrain(Pilot.class);
query.descend("points").constrain(new Integer(100));
listResult(result);
}
有一个场景,我们不想通过紧缺属性值来查询而是同过指定范围来查询.这个功能由Constraint API 提供.首先,让我们查询名字不是"Michael Schumacher"的所有Pilots
QueryExample.java: retrieveByNegation
public static void retrieveByNegation(ObjectContainer db) ...{
Query query=db.query();
query.constrain(Pilot.class);
query.descend("name").constrain("Michael Schumacher").not();
ObjectSet result=query.execute();
listResult(result);
}
这儿是个取反的布尔运算,其他的布尔运算也很接近.
QueryExample.java: retrieveByConjunction
public static void retrieveByConjunction(ObjectContainer db) ...{
Query query=db.query();
query.constrain(Pilot.class);
Constraint constr=query.descend("name")
.constrain("Michael Schumacher");
query.descend("points")
.constrain(new Integer(99)).and(constr);
ObjectSet result=query.execute();
listResult(result);
QueryExample.java: retrieveByDisjunction
public static void retrieveByDisjunction(ObjectContainer db) ...{
Query query=db.query();
query.constrain(Pilot.class);
Constraint constr=query.descend("name")
.constrain("Michael Schumacher");
query.descend("points")
.constrain(new Integer(99)).or(constr);
ObjectSet result=query.execute();
listResult(result);
}
}
我们可以比较给定的值来约束.
QueryExample.java: retrieveByComparison
public static void retrieveByComparison(ObjectContainer db) ...{
Query query=db.query();
query.constrain(Pilot.class);
query.descend("points")
.constrain(new Integer(99)).greater();
ObjectSet result=query.execute();
listResult(result);
}
这个查询接口允许默认值的查询.
QueryExample.java: retrieveByDefaultFieldValue
public static void retrieveByDefaultFieldValue(
ObjectContainer db) ...{
Pilot somebody=new Pilot("Somebody else",0);
db.set(somebody);
Query query=db.query();
query.constrain(Pilot.class);
query.descend("points").constrain(new Integer(0));
ObjectSet result=query.execute();
listResult(result);
db.delete(somebody);
}
也可以对结果排序
QueryExample.java: retrieveSorted
public static void retrieveSorted(ObjectContainer db) ...{
Query query=db.query();
query.constrain(Pilot.class);
query.descend("name").orderAscending();
ObjectSet result=query.execute();
listResult(result);
query.descend("name").orderDescending();
result=query.execute();
listResult(result);
}
这些组合都是随意的,请你试试.也许有许多查询情景可能采用constrains的查询接口无法实现,不过不用担心,你可以
更随意的应用Evaluations来实现.Evaluations 的讨论在 Evaluations chapter.