一般情况下,用db4o查询到的数据都是你的POJO的实例(当你读取某个实例的属性时,db4o会调用activate方法激活该实例)。这种机制非常的不利于你读取较大数据量的情形,比如你跑报表的时候,你的某个报表包含10000条记录(其实在odb不应该使用“记录”这一说法),如果只考虑顶层数据对象的激活,就得硬生生实例化10000个对象。如果你执行的是一个聚集操作,比如求10000个数据的平均值,你将得到10000个对象,然后你逐一读取,求均值,很明显,这很不格算。资源都浪费在实例化对象上面了。理论上这会是一个瓶颈,实际上也是如此。
db4o目前还没有直接提供此类支持(db4o网站上倒是有一个关于Aggregate Queries的描述,见http://developer.db4o.com/Projects/html/projectspaces/db4o_product_design/aggregate_queries.html,不过一直没人去实现它)
那么我可不可以在不实例化对象的前提下,直接读取数据呢? 我觉得这是可以的。至少有两个途径:
1,自己读取db4o的bytes,得到自己需要的数据。在调试过程中,发现db4o在实例化POJO对象之前,是从bytes读取数据的,比如这个bytes:
[-1 , -4 , -86 , 11 , 10 , 0 , 0 , 0 , 67 , -92 , -1 , -1 , -1 , -1 , -1 , -1 , 19 , 6 , 0 , 0 , 0 , 67 , 0 , 2 , 95 , -42 , 0 , 28 , -9 , -102 , 0 , 0 , 2 , 49 , 0 , 0 , 0 , 32 , 0 , 1 , 97 , -63 , 0 , 0 , 11 , -123 , 0 , 0 , 0 , -67 , 0 , 0 , 1 , 116 , 0 , 0 , 0 , 113 , 0 , 0 , 0 , 76 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 45 , 7 , -62 , 76 , -22 , 0 , 0 , 0 , 87 , 0 , 0 , 0 , 26 , 70 , 0 , 0 , 0 , 11 , 115 , 0 , 121 , 0 , 115 , 0 , 95 , 0 , 109 , 0 , 105 , 0 , 103 , 0 , 114 , 0 , 97 , 0 , 116 , 0 , 101 , 0 , 0 , 0 , 0 , 36 , 99 , 0 , 98 , 0 , 55 , 0 , 57 , 0 , 53 , 0 , 52 , 0 , 101 , 0 , 49 , 0 , 45 , 0 , 52 , 0 , 55 , 0 , 53 , 0 , 57 , 0 , 45 , 0 , 52 , 0 , 99 , 0 , 53 , 0 , 97 , 0 , 45 , 0 , 98 , 0 , 53 , 0 , 100 , 0 , 56 , 0 , 45 , 0 , 48 , 0 , 49 , 0 , 100 , 0 , 101 , 0 , 102 , 0 , 51 , 0 , 52 , 0 , 56 , 0 , 54 , 0 , 48 , 0 , 51 , 0 , 99 , 0 , 0 , 0 , 0 , -72 , 80 , 0 , 108 , 0 , 101 , 0 , 97 , 0 , 115 , 0 , 101 , 0 , 32 , 0 , 101 , 0 , 45 , 0 , 109 , 0 , 97 , 0 , 105 , 0 , 108 , 0 , 32 , 0 , 116 , 0 , 104 , 0 , 101 , 0 , 32 , 0 , 67 , 0 , 68 , 0 , 65 , 0 , 32 , 0 , 116 , 0 , 111 , 0 , 32 , 0 , 100 , 0 , 112 , 0 , 101 , 0 , 100 , 0 , 105 , 0 , 110 , 0 , 101 , 0 , 108 , 0 , 108 , 0 , 105 , 0 , 64 , 0 , 109 , 0 , 105 , 0 , 99 , 0 , 104 , 0 , 105 , 0 , 103 , 0 , 97 , 0 , 110 , 0 , 104 , 0 , 101 , 0 , 97 , 0 , 114 , 0 , 116 , 0 , 46 , 0 , 99 , 0 , 111 , 0 , 109 , 0 , 46 , 0 , 32 , 0 , 83 , 0 , 104 , 0 , 101 , 0 , 32 , 0 , 119 , 0 , 105 , 0 , 108 , 0 , 108 , 0 , 32 , 0 , 115 , 0 , 101 , 0 , 101 , 0 , 32 , 0 , 116 , 0 , 104 , 0 , 97 , 0 , 116 , 0 , 32 , 0 , 105 , 0 , 116 , 0 , 32 , 0 , 103 , 0 , 101 , 0 , 116 , 0 , 115 , 0 , 32 , 0 , 116 , 0 , 111 , 0 , 32 , 0 , 116 , 0 , 104 , 0 , 101 , 0 , 32 , 0 , 97 , 0 , 112 , 0 , 112 , 0 , 114 , 0 , 111 , 0 , 112 , 0 , 114 , 0 , 105 , 0 , 97 , 0 , 116 , 0 , 101 , 0 , 32 , 0 , 80 , 0 , 73 , 0 , 46 , 0 , 32 , 0 , 73 , 0 , 116 , 0 , 32 , 0 , 109 , 0 , 97 , 0 , 121 , 0 , 32 , 0 , 32 , 0 , 101 , 0 , 110 , 0 , 100 , 0 , 32 , 0 , 117 , 0 , 112 , 0 , 32 , 0 , 98 , 0 , 101 , 0 , 105 , 0 , 110 , 0 , 103 , 0 , 32 , 0 , 115 , 0 , 111 , 0 , 109 , 0 , 101 , 0 , 111 , 0 , 110 , 0 , 101 , 0 , 32 , 0 , 101 , 0 , 108 , 0 , 115 , 0 , 101 , 0 , 32 , 0 , 114 , 0 , 97 , 0 , 116 , 0 , 104 , 0 , 101 , 0 , 114 , 0 , 32 , 0 , 116 , 0 , 104 , 0 , 97 , 0 , 110 , 0 , 32 , 0 , 68 , 0 , 114 , 0 , 46 , 0 , 32 , 0 , 79 , 0 , 39 , 0 , 68 , 0 , 111 , 0 , 110 , 0 , 110 , 0 , 101 , 0 , 108 , 0 , 108 , 0 , 46 , 0 , 32 , 0 , 67 , 0 , 68 , 0 , 65 , 0 , 32 , 0 , 101 , 0 , 109 , 0 , 97 , 0 , 105 , 0 , 108 , 0 , 101 , 0 , 100 , 0 , 32 , 0 , 50 , 0 , 47 , 0 , 49 , 0 , 55 , 0 , 47 , 0 , 48 , 0 , 54 , 0 , 0 , 0 , 0 , 14 , 77 , 0 , 105 , 0 , 99 , 0 , 104 , 0 , 105 , 0 , 103 , 0 , 97 , 0 , 110 , 0 , 32 , 0 , 72 , 0 , 101 , 0 , 97 , 0 , 114 , 0 , 116 , 0]
用
println new String([-1 , -4 , -86 , 11 , 10 , 0 , 0 , 0 , 67 , -92 , -1 , -1 , -1 , -1 , -1 , -1 , 19 , 6 , 0 , 0 , 0 , 67 , 0 , 2 , 95 , -42 , 0 , 28 , -9 , -102 , 0 , 0 , 2 , 49 , 0 , 0 , 0 , 32 , 0 , 1 , 97 , -63 , 0 , 0 , 11 , -123 , 0 , 0 , 0 , -67 , 0 , 0 , 1 , 116 , 0 , 0 , 0 , 113 , 0 , 0 , 0 , 76 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 45 , 7 , -62 , 76 , -22 , 0 , 0 , 0 , 87 , 0 , 0 , 0 , 26 , 70 , 0 , 0 , 0 , 11 , 115 , 0 , 121 , 0 , 115 , 0 , 95 , 0 , 109 , 0 , 105 , 0 , 103 , 0 , 114 , 0 , 97 , 0 , 116 , 0 , 101 , 0 , 0 , 0 , 0 , 36 , 99 , 0 , 98 , 0 , 55 , 0 , 57 , 0 , 53 , 0 , 52 , 0 , 101 , 0 , 49 , 0 , 45 , 0 , 52 , 0 , 55 , 0 , 53 , 0 , 57 , 0 , 45 , 0 , 52 , 0 , 99 , 0 , 53 , 0 , 97 , 0 , 45 , 0 , 98 , 0 , 53 , 0 , 100 , 0 , 56 , 0 , 45 , 0 , 48 , 0 , 49 , 0 , 100 , 0 , 101 , 0 , 102 , 0 , 51 , 0 , 52 , 0 , 56 , 0 , 54 , 0 , 48 , 0 , 51 , 0 , 99 , 0 , 0 , 0 , 0 , -72 , 80 , 0 , 108 , 0 , 101 , 0 , 97 , 0 , 115 , 0 , 101 , 0 , 32 , 0 , 101 , 0 , 45 , 0 , 109 , 0 , 97 , 0 , 105 , 0 , 108 , 0 , 32 , 0 , 116 , 0 , 104 , 0 , 101 , 0 , 32 , 0 , 67 , 0 , 68 , 0 , 65 , 0 , 32 , 0 , 116 , 0 , 111 , 0 , 32 , 0 , 100 , 0 , 112 , 0 , 101 , 0 , 100 , 0 , 105 , 0 , 110 , 0 , 101 , 0 , 108 , 0 , 108 , 0 , 105 , 0 , 64 , 0 , 109 , 0 , 105 , 0 , 99 , 0 , 104 , 0 , 105 , 0 , 103 , 0 , 97 , 0 , 110 , 0 , 104 , 0 , 101 , 0 , 97 , 0 , 114 , 0 , 116 , 0 , 46 , 0 , 99 , 0 , 111 , 0 , 109 , 0 , 46 , 0 , 32 , 0 , 83 , 0 , 104 , 0 , 101 , 0 , 32 , 0 , 119 , 0 , 105 , 0 , 108 , 0 , 108 , 0 , 32 , 0 , 115 , 0 , 101 , 0 , 101 , 0 , 32 , 0 , 116 , 0 , 104 , 0 , 97 , 0 , 116 , 0 , 32 , 0 , 105 , 0 , 116 , 0 , 32 , 0 , 103 , 0 , 101 , 0 , 116 , 0 , 115 , 0 , 32 , 0 , 116 , 0 , 111 , 0 , 32 , 0 , 116 , 0 , 104 , 0 , 101 , 0 , 32 , 0 , 97 , 0 , 112 , 0 , 112 , 0 , 114 , 0 , 111 , 0 , 112 , 0 , 114 , 0 , 105 , 0 , 97 , 0 , 116 , 0 , 101 , 0 , 32 , 0 , 80 , 0 , 73 , 0 , 46 , 0 , 32 , 0 , 73 , 0 , 116 , 0 , 32 , 0 , 109 , 0 , 97 , 0 , 121 , 0 , 32 , 0 , 32 , 0 , 101 , 0 , 110 , 0 , 100 , 0 , 32 , 0 , 117 , 0 , 112 , 0 , 32 , 0 , 98 , 0 , 101 , 0 , 105 , 0 , 110 , 0 , 103 , 0 , 32 , 0 , 115 , 0 , 111 , 0 , 109 , 0 , 101 , 0 , 111 , 0 , 110 , 0 , 101 , 0 , 32 , 0 , 101 , 0 , 108 , 0 , 115 , 0 , 101 , 0 , 32 , 0 , 114 , 0 , 97 , 0 , 116 , 0 , 104 , 0 , 101 , 0 , 114 , 0 , 32 , 0 , 116 , 0 , 104 , 0 , 97 , 0 , 110 , 0 , 32 , 0 , 68 , 0 , 114 , 0 , 46 , 0 , 32 , 0 , 79 , 0 , 39 , 0 , 68 , 0 , 111 , 0 , 110 , 0 , 110 , 0 , 101 , 0 , 108 , 0 , 108 , 0 , 46 , 0 , 32 , 0 , 67 , 0 , 68 , 0 , 65 , 0 , 32 , 0 , 101 , 0 , 109 , 0 , 97 , 0 , 105 , 0 , 108 , 0 , 101 , 0 , 100 , 0 , 32 , 0 , 50 , 0 , 47 , 0 , 49 , 0 , 55 , 0 , 47 , 0 , 48 , 0 , 54 , 0 , 0 , 0 , 0 , 14 , 77 , 0 , 105 , 0 , 99 , 0 , 104 , 0 , 105 , 0 , 103 , 0 , 97 , 0 , 110 , 0 , 32 , 0 , 72 , 0 , 101 , 0 , 97 , 0 , 114 , 0 , 116 , 0] as byte[], 'utf8')
把它打出来,是这样的:
??C???????C_???1 a???tqL-?L?WFsys_migrate$cb7954e1-4759-4c5a-b5d8-01def348603c?Please e-mail the CDA to [email protected]. She will see that it gets to the appropriate PI. It may end up being someone else rather than Dr. O'Donnell. CDA emailed 2/17/06Michigan Heart
有一丝希望的曙光。不过,几经调试,我愣是没有理出个头绪,搞得一团乱麻。我长叹一声,算了,想其它的辙吧。
2, 在阅读db4o源码的过程中,发现在Evaluation接口中有这么一段文字:
希望的曙光再次出现。
啥也不说了,上代码:
DirectCandidateAccessor.java :
package com.db4o.query; import com.db4o.internal.query.processor.QCandidate; import groovy.lang.Closure; /** * Created by IntelliJ IDEA. * User: S.C. * Date: Jan 4, 2011 * Time: 11:29:41 AM * To change this template use File | Settings | File Templates. */ public class DirectCandidateAccessor implements Evaluation { private Closure callback; public DirectCandidateAccessor(Closure callback) { this.callback = callback; } public void evaluate(Candidate candidate) { QCandidate qc = (QCandidate) candidate; int _key = qc._key; Object _value = qc.getObject(); //System.out.println("Direct Access :: key: " + _key + ", value: " + _value); this.callback.call(new Object[]{_key, _value}); } }
QQueryBase#constrain :
public Constraint constrain(Object example) { // +by S.C. 09-Dec-2010 ==> if(example instanceof Pattern) { return constrain(new RegexConstraint((Pattern)example)); } // +by S.C. 09-Dec-2010 <== // +by S.C. 04-Jan-2011 ==> if(example instanceof Closure) { return constrain(new DirectCandidateAccessor((Closure)example)); } // +by S.C. 04-Jan-2011 <== synchronized (streamLock()) { ReflectClass claxx = reflectClassForClass(example); if (claxx != null) { return addClassConstraint(claxx); } QConEvaluation eval = Platform4.evaluationCreate(_trans, example); if (eval != null) { return addEvaluationToAllConstraints(eval); } Collection4 constraints = new Collection4(); addConstraint(constraints, example); return toConstraint(constraints); } }
这里就加了这么一句
if(example instanceof Closure) { return constrain(new DirectCandidateAccessor((Closure)example)); }
小试牛刀:
def callback = {k,v-> println "key: $k, value: $v" } Site.findAll(name:callback,'pi.name':callback,id:callback).size()
比起
def callback = {k,v-> println "key: $k, value: $v" } Site.findAll(name:callback,'pi.name':callback,id:callback).each{println it}
来,不是一般的快,因为后者做了实例化,而前者避免了这一操作。