NQ
你不想使用你使用的编程语言来构造查询条件?它是100%类型安全并且100%编译时检查和100%可分解.不想通过面向对象的
原则来实现查询? 来吧!进入NQ
NQ是主要的查询接口,它被推荐使用在你的应用中查询数据库,因为它采用你使用的编程语言的语法,它是完美的标准,对于
将来也是安全的选择.
NQ支持所有平台.
观念
NQ的感念来自下面的两篇文章:
Cook/Rosenberger, Native Queries for Persistent Objects, A Design White Paper
Cook/Rai, Safe Query Objects: Statically Typed Objects as Remotely Executable Queries
原则
NQ通过运行一行或者多行代码而不是一个对象的所有实例.NQ表达式返回真,标记指定的实例作为查询的结果集的一部分,
db4o试图优化NQ表达式,通过索引而不是真实的实例.
简单的例子:
让我们看看采用db4o所支持的编程语言,用NQ是多么的简单.
Java5:
PrimitiveExample.java: primitiveQuery
public static void primitiveQuery(ObjectContainer db)...{
List pilots = db.query(new Predicate() ...{
public boolean match(Pilot pilot) ...{
return pilot.getPoints() == 100;
}
});
}
Java1.2-1.4:
NQExample.java: primitiveQuery
public static void primitiveQuery(ObjectContainer db)...{
List <Pilot> pilots = db.query(new Predicate<Pilot>() ...{
public boolean match(Pilot pilot) ...{
return pilot.getPoints() == 100;
}
});
}
Java1.1:
PrimitiveExample.java: primitiveQuery1
public static void primitiveQuery1(ObjectContainer db)...{
List pilots = db.query(new PilotHundredPoints());
}
PilotHundredPoints.java
/**//* Copyright (C) 2004 - 2006 db4objects Inc.
http://www.db4o.com
*/
import com.db4o.query.Predicate;
public class PilotHundredPoints extends Predicate ...{
public boolean match(Pilot pilot) ...{
return pilot.getPoints() == 100;
}
}
顺便提醒一下上边的语法:
对于所有的方言不支持通用类型,NQ按照习惯工作.一个继承Predicate类的对象有一个返回布尔值方法match()或者Match()
这个方法有一个参数.
Java: boolean match(Pilot candidate);
当你使用NQ时,别忘记用先进IDE来输入NQ表达式.如果你使用了模板和自动完成功能.
下面是如何在Eclipse3.1中配置:
1.打开菜单,选择 Window + Preferences + Java + Editor + Templates + New
名字为np,确保选择java在context中,拷贝下面内容到Pattern field中:
List <${extent}> list = db.query(new Predicate <${extent}> () {
public boolean match(${extent} candidate){
return true;
}
});
现在,你可以创建NQ查询通过n + q + Control-Space
这些简单的功能在许多先进的IDE是有效的.
深入的例子
对于复杂的查询,NQ语法是非常准确并且便于很快的书写.让我们比较SODA查询给定名字或者给定成绩区间的pilot.
存储:
NQExample.java: storePilots
public static void storePilots(ObjectContainer db) ...{
db.set(new Pilot("Michael Schumacher",100));
db.set(new Pilot("Rubens Barrichello",99));
}
通过SODA查询:
NQExample.java: retrieveComplexSODA
public static void retrieveComplexSODA(ObjectContainer db) ...{
Query query=db.query();
query.constrain(Pilot.class);
Query pointQuery=query.descend("points");
query.descend("name").constrain("Rubens Barrichello")
.or(pointQuery.constrain(new Integer(99)).greater()
.and(pointQuery.constrain(new Integer(199)).smaller()));
ObjectSet result=query.execute();
listResult(result);
}
下面是通过NQ语法实现相同的查询.它是跟容易自动完成可分解等其他IDE特性,并且还是运行期检查.
NQExample.java: advancedQuery
public static void advancedQuery(ObjectContainer db)...{
List <Pilot> result = db.query(new Predicate<Pilot>() ...{
public boolean match(Pilot pilot) ...{
return pilot.getPoints() > 99
&& pilot.getPoints() < 199
|| pilot.getName().equals("Rubens Barrichello");
}
});
}
随意的查询
.
基本而言,你可以有效地使用NQ,原则上,你可以运行使用NQ任意随意的查询,你仅仅要考虑其他的影响,特别是
可能影响持久化的对象.
让我们运行一个例子来包括更多的有效语言特性:
NQExample.java: retrieveArbitraryCodeNQ
public static void retrieveArbitraryCodeNQ(ObjectContainer db) ...{
final int[] points=...{1,100};
ObjectSet result=db.query(new Predicate<Pilot>() ...{
public boolean match(Pilot pilot) ...{
for(int i=0;i<points.length;i++) ...{
if(pilot.getPoints()==points[i]) ...{
return true;
}
}
return pilot.getName().startsWith("Rubens");
}
});
listResult(result);
}
NQ 性能
对于NQ的一个缺点必须要指出:NO引擎试图分析NQ表达式,并把它们转化为SODA,这对于所有的查询时不可能的.对于某些
查询,这种分析将是非常困难,如何这样,db4o将不得不实例化一些持久对象来执行NQ代码.db4o将试图分析部分NQ表达式
来保证对象实例尽量的少.
db4o社区有对NQ优化团队,你可以把你的结果和反馈给db4o组织。当前优化细节在NQ Optimization 章节。
对于当前的实现,上面除了随意的查询外,其他的都进行了优化。