??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品国产欧美,久久人91精品久久久久久不卡,超碰97人人在线http://www.aygfsteel.com/jiangshachina/category/23791.html同是Java爱好者,盔R何必曾相识Q?lt;br>    a cup of Java, cheers!zh-cnWed, 14 Dec 2011 16:30:39 GMTWed, 14 Dec 2011 16:30:39 GMT60深入db4o(?http://www.aygfsteel.com/jiangshachina/archive/2007/12/05/164430.htmlSha JiangSha JiangWed, 05 Dec 2007 04:31:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2007/12/05/164430.htmlhttp://www.aygfsteel.com/jiangshachina/comments/164430.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2007/12/05/164430.html#Feedback8http://www.aygfsteel.com/jiangshachina/comments/commentRss/164430.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/164430.html深入db4o
    q是Rick Grehan发表?/span>TheServerSide上的一关于面向对象数据库--db4o的文?/span>Q较全面Cl了db4o的关键特性,希望对大家认?a >db4o能有所帮助?2007.12.07最后更?

    db4o-针对对象的数据库-是一个完全的对象数据库;它以使对象在其生命周期中-无论是在数据库内或是在外-都保持着它们的本性这样一U方式操U对象。不论类的复杂性如何,对象的内容,l构和关p都能够被保存?br />     更准地_db4o是一个数据库引擎Q你只要它的一个jar文g包含C的数据库应用的类路径中就可以使用它了(臛_对于Java是这L)。所以,db4oq行在与你的应用E序相同的进E空间中Qƈ能被直接地调用;它不需要类g在ODBC或JDBC中用的驱动文g。db4o存在针对JavaQ?NET和Mono的版本;它们在功能上都彼此相{?事实上,使用.NET创徏的db4o数据库也能由JavaE序讉KQ反之亦然?
    db4o是开源的。可执行文gQ源代码和文档可从http://www.db4objects.com/中下载。广泛的例子E序Q和一个活跃的用户C֌一P也都可以从这个站点中扑ֈ?br />     db4o最引h的特性之一是它在易性与强大的功能之间的显著q。一斚wQ它的API是如此地易于掌握和方便用,即是初学者也能在相同的时间内创徏一个功能完备的数据库对象。另一斚wQ这些相同的API也提供了更底层的能够深入调用数据库引擎的ҎQ以允许核心开发者ؓ了得到适当的性能而能深入到该引擎的内部中去调整db4o的工兗?br />     db4o的特性就是最好的证明--q胜q只是讨?-所以我们将通过CZq种Ҏ去证明db4o。然而,我们必须牢记本文通篇只是展示了db4oҎ中的一部分|了。感兴趣的朋友会发现Z知晓该数据库引擎的全部功能而去查阅db4o的文档所q旉是值得的?br />
db4o基础
    让我们以初学者用db4o时可能会做的事情开始:定义了一些类Q然后持久化q些cȝ对象。我们所假定的类为同样也是假定的QA目做一个跟t测试的pȝ。我们的pȝ׃个类l成Q首先是TestSuitec:
    public class TestSuite {
        private String name;  // Test Suite name
        private String description;
        private String configuration;
        private char overallScore;
        private ArrayList <TestCase> cases;
        private long dateExec;
        ... <remainder of TestSuite definition> ...
    }
    TestSuite是TestCase对象的容器,(一个测试用例就是一个可单独执行的测试程?-相关的测试用例组合成一个测试组)。测试组使用额外的,全局的数据成员,每个数据成员的用途也是相Ҏ昄Qconfiguration记录被测试的指定pȝQoverallScore是对整个试l一个简要的评分('P'代表通过Q?F'代表p|Q?B'代表被阻塞,{等?QdateExec是一个毫U的域Q标识该试l被执行时的日期与时刅R是ArrayList对象的cases含有单个的测试用例,由TestCasecd义:
    public class TestCase {
        private String name;
        private String comment;
        private char status;
        private long duration;
        private float result;
        ... <remainder of TestCase definition> ...
    }
    每个试用例都有一个名Uͼ形式自由的注释字D,状?通过或失?Q持l时间和l果(例如Qؓ了与试-字节/U的吞吐?的Q意数据关??br />     因ؓ我们所x是db4o的用,所以我们不惛_描述q些cȝ使用l节上停留。就让我们简单地_我们已经执行了一个特别地试l中所有的试用例Q将试的结果存攑֜一个TestSuite对象?与TestCase对象相关的ArrayList对象cases?Q然后关闭数据库。是不是太容易了?br />     // Create the database
    new File("testsuites.YAP").delete();
    ObjectContainer db = Db4o.openFile("testsuites.YAP");
    // Store the TestSuite object
    db.set(testsuite);
    // Close the database
    db.close();
    是它。弹指一挥间Q你已l做C?当然Qؓ了保持简z,我们L了创建TestSuite对象和它的TestCaselg的细?
    停下来想想上qC码做了什么事情。特别要考虑你没有看到的--db4o已经做了但还未被告之的事情?br />     首先Q我们不需要告诉db4oM关于TestSuitecȝl构的信息;不需要我们的帮助Qdb4op发现q个l构。利用Java反射机制的能力,db4o定TestSuitecȝl构Qƈ勑֋cȝ装配方式以推导出此类对象的成员与关键数据?br />     W二Q我们不必徏议db4od注ArrayList。不仅我们不必将ArrayList的大告诉db4oQ而且我们也不必把它里面的内容告诉db4o。正如db4o在它刚接触testsuite对象时就能够发现它所需要的一切,db4o也能知道它所需要的关于(在ArrayList中的)TestCase对象的所有信息?br />     l果是Q如果我们把testsuite作ؓ一个Q意宠大而复杂的对象树的根,db4o能找到ƈ存储整个树而不需要我们的M协助。所以,存储q个处于栚w的对象testsuite也就是存储了整个ArrayList对象?br />     最后,我们也没有必要求db4o以事务的保护性方式去调用setҎ。Q何会修改ObjectContainer(表示数据库的db4o对象)的调用都会自动地开启一个事务,除非已经有一个活跃的事务了。此外还会调用closeҎȝ止这个事务,所以上qC码等价于Q?br />     db.startTransaction();
    db.set(testsuite);
    db.commitTransaction();
    db.close();
    此处的startTransaction和commitTransactionҎ是ؓ了证明我们的观点而虚构的。db4o也确实有昄地提交或中止事务的方法,但ؓ了原先的代码够的z我们没有用这些方法。db4o隐式的事务得数据库能够一直处于一致的状态;一旦commitҎ已经执行了,数据库的完整性就能够得到保证Q甚x发生了灾难性失败也能如此?br />
查询I - QBE
    有了已经存于数据库中的对象,下一步我们想要展C的操作肯定就是查询和恢复。db4o提供了三U查询APIQ有一U简单,有一U优雅,q有一U则复杂。每一UAPI都有其所长,q用于不同的查询条g。以db4o的眼光来看,你选择哪一UAPIq没有关p:它们都是可兼容的?br />     我们以简单的API开始:query by exampel(QBE)?br />     使用QBE是如此的ҎQؓ你的查询目标构徏一?模板'对象Q然后把它传入ObjectContainer的queryҎ。实际上Q你是告诉db4o'L到所有与q个对象看v来一L对象'?q与JavaSpaces查询API非常怼Qؓ了清楚地了解如何处理基本数据cdQ可以看下面的内容,db4o的处理方式与JavaSpaces不同。也要注意,JavaSpace Entry对象期望使用public字段Qdb4o则没有这U要求?
    假设一个测试组名ؓ"Network Throughput"Q我们想取出q个试l执行的所有测试以便我们能定p|了的试所占的癑ֈ?ZTestSuite的overalScore?。用QBEQ完成该工作的代码如下:
    // Open the database
    ObjectContainer db = Db4o.openFile("testsuites.YAP");

    // Instantiate the template object, filling in
    // only the name field
    testTemplate = new TestSuite("Network Throughput");

    // Execute the query
    ObjectSet result = db.get(testTemplate);
    fails = 0.0f;
    total = 0.0f;

    // Step through results,
    while(result.hasNext())
    {
        testsuite = (TestSuite)result.next();
        if(testsuite.getOverallScore()=='F')
        fails += 1.0f;
        total += 1.0f;
    }

    if(total == 0.0f)
        System.out.println("No tests of that type found.");
    else
    {
        System.out.println("Percent failed: " + (fails/total * 100.0f) + "%");
        System.out.println("Total executed: " + total);
    }
    db.close();
    在上面的代码中,testTemplate是QBE的模板对象。注意,只有它的name字段有真实的|所有其它的成员变量不是为null是?。Null?字段不参与QBE查询Q因此,调用db.getҎ׃q回在该数据库中name字段匚w"Network Throughput"的所有TestSuite对象。匹配的TestSuite对象返回在一个ObjectSetl果对象中。上qC码遍历该l果Q取出对象,然后计算l果q展C出来?br />     QBE明显的优点就是它的简易性。不需要掌握其它单独的查询语言。另外,QBE也是cd安全的:你不需要创Z个类gSQL的查询语?br />     SELECT TestSuite.overallScore FROM TestSuite WHERE TestSuite.name = 200.0
    另一斚wQ由于该查询是由Java代码创徏的,~译器不会允怽把一个Q点Dl一个String字段Q反之亦然?br />     QBE明显的缺点就是它只能执行"{于"查询。另外,QBE使用null值去定不参与查询的String或对象引用成员变量,使用0值去指定不参与查询的数字字段。所以,例如Q我不能发明一个QBE查询去获得所有result字段的gؓ0的TestCase对象?br />     更ؓ_的查询要求一个能力更强的查询机制Q而db4o恰恰有q样一U机制?br />
查询方式II - 原生查询(Native Query)
    db4o的原生查询系l应该是能想像得到的最具弹性的查询机制。不像用数据库查询语言L建查询,你是使用"无格式的普通Java语句"L造原生查询。原生查询用两种手段d现这件不可思意的工作:一个是Predicatec;另一个是QueryComparator接口。这个类包含一个可重蝲?overrideable)回调ҎQ该Ҏ指定如何从数据库中选择对象(如果你愿意,你将会看到查询语句的M....)。这个接口只声明了一个方法,该方法用于指明如何对查询l果q行排序?br />     作ؓ一个例子,我们假设x到在l定的一周内执行q了的d分ؓ"failed"Q但与之兌的测试用例中有超q一半的被评?passed"的测试组。这不是一个简单的"{于"查询Q所以它不能使用QBE构徏?br />     然而,db4o的原生查询可以直接地生成该查询。首先,我们l承db4o的Predicatec:
    // Predicate class sub-class for native query example
    public class NativeQueryQuery extends Predicate<TestSuite>
    {
        ObjectContainer db;
        private long startdate;
        private long enddate;

        // 构造器要在本地获得ObjectContainer对象和日期范?br />         public NativeQueryQuery(ObjectContainer _db,
            long _start, long _end)
        {
            db = _db;
            startdate = _start;
            enddate = _end;
        }

        // q就是查询的M
        public boolean match(TestSuite testsuite)
        {
            float passed;
            float total;
            TestCase testcase;

            // 判断testsuite是否在指定的日期范围?br />             if(testsuite.getDateExec()<startdate ||
              testsuite.getDateExec()>enddate) return false;

            // 如果该测试组对象中没有测试用例对象,则拒l将该测试组对象攑օ查询l果?br />             if(testsuite.getNumberOfCases()==0)
                return false;

            // 查该试l对象中的测试用例的通过率是否超q?0%
            passed = 0.0f;
            total = 0.0f;
            for(int i=0; i<testsuite.getNumberOfCases(); i++)
            {
                testcase = testsuite.getTestCase(i);
                if(testcase.getStatus()=='P')
                    passed+=1.0f;
                total+=1.0f;
            }
            if((passed/total)<.5) return false;
                return true;
        }
    }
    注意在这个类的用中使用了Java泛型语义Q这是告诉db4o只去取TestSuite对象。当查询执行ӞTestSuite对象׃传入matchҎ(我们之前提到q的回调Ҏ)Q如果传入的TestSuite对象W合查询规范该方法就q回trueQ否则就q回false?br />     matchҎ中的代码首先定侯选对象是否是在一周的日期范围内。如果是Q则循环该对象中的成员变量测试用例的对象Q计出所有通过了的试用例的L。如果,得到的通过率小?0%Q该试l就被拒l;否则Q就让它通过?br />     我们可以使用如下的代码准地展示该查询程序:
    . . .
    TestSuite testsuite;
    NativeQueryQuery nqqClass;
    Date now;

    // Open the database
    ObjectContainer db = Db4o.openFile("testsuites.YAP");

    // Instantiate a NativeQueryQuery object,
    // setting the start and end dates for
    // any test in the past week
    // 604800000 = milliseconds in a week
    now = new Date();
    nqqClass = new NativeQueryQuery(db,
    now.getTime()-604800000L,
    now.getTime());

    // Execute the query and display the
    // results
    System.out.println("Results:");
    ObjectSet results = db.query(nqqClass);
    if(results.isEmpty())
        System.out.println("  NOTHING TO DISPLAY");

    while(results.hasNext())
    {
        testsuite = (TestSuite)(results.next());
        System.out.println(testsuite.toString());
    }

    db.close();
    . . .
    可以把原生查询想像成q样Q目标类的对象一个接一个从数据库中取出Q然后把它们传入matchҎ中。只有那些被matchҎq回true的对象才会置于查询结果ObjectSet对象中。基本上可以_如果你会知道如何写Java代码Q那么你q道如何写原生查询?br />     那么排序呢?如果x日期的升序排列查询结果,我们p实现QueryComparator接口Q如下所C:
    public class NativeQuerySort implements QueryComparator<TestSuite>{
        public int compare(TestSuite t1, TestSuite t2)
        {
            if (t1.getDateExec() < t2.getDateExec()) return -1;
            if (t1.getDateExec() > t2.getDateExec()) return 1;
            return 0;
        }
     }
compareҎ的作用十分明显。那些在查询中得以胜出的对象会成对的传入compareҎQ如果第一个对象会排在W二个对象之前,相同或之后的位置Q该Ҏ׃分别q回一个小于,{于或大?的倹{ؓ了准地说明Ҏ询结果的排序Q我们实例化NativeQuerySortQƈ把对queryҎ的调用修Ҏ如下Q?br />     . . .
    // Instantiate the sort class
    nqsClass = new NativeQuerySort();
    . . .
    ObjectSet results = db.query(nqqClass, nqsClass);
    . . .
其它的代码仍然与原先的保持一致?br />     好怀疑的读者可能会抱怨道Q原生查询只是一U编E上的小伎俩--相比较于直接L到所有的TestSuite对象然后再排除其中不W合条g的对象这LE序Q原生查询ƈ不快?br />     是的Q但q不十分准确。原生能够被优化。你所需要做的只是把两个jar文g--db4o-xxx-nqopt.jar(xxx表示db4o的版?和bloat.jar--|于CLASSPATH环境变量中。在查询执行的时候,q些cd中的代码会对(在matchҎ?例如基本数据cd比较Q算术和布尔表达式,单的对象成员讉KQ以及更多方面的l构q行优化。这个被支持的优化的列表在不停的增长Q因为db4o引擎q在扩展优化的范围?br />
查询方式III - S.O.D.A.
    db4o独一无二的能力之一是它的API被分层了。开发者能够选择通过高层?-赋予数据库引擎相当大的自由度Q让它决定如何去实现它的操作--或者开发者也可以使用一U更直接地方式去讉Kdb4o。后一U选择为程序员qx了更多的负担Q程序员必须更加心地引导数据库引擎的内部工作。但回报是得到一个更快,能力更强的数据库应用?br />     db4o的S.O.D.A.(Simple Object Data Access)查询机制是该层ơAPI的一个完的例子。S.O.D.A.是db4o的内部查询系l?-QBE和原生查询都被翻译成了S.O.D.A.。然而,应用E序也能直接地调用S.O.D.A.?br />     假设我们x到所有名?Network Throughput"Q且臛_拥有一个其result字段--我们使用q个参数作ؓ字节/U的量度--不小于指定?比方_100)的测试用例的试l。ؓ该请求而做的S.O.D.A.查询可能像q样Q?br />     . . .
    TestSuite testsuite;

    // Open the database
    ObjectContainer db = Db4o.openFile("testsuites.YAP");

    // Construct the query
    Query query = db.query();
    query.constrain(TestSuite.class);
    Constraint nameConst = query.descend("name").
    constrain("Network Throughput");
    query.descend("cases").descend("result").
    constrain(100.0f).smaller().and(nameConst);

    System.out.println("Results:");
    // Execute the query
    ObjectSet result = query.execute();
    if(result.isEmpty())
    System.out.println("NOTHING TO DISPLAY");

    while(result.hasNext())
    {
        testsuite = (TestSuite)(result.next());
        System.out.println(testsuite.toString());
    }

    db.close();
    . . .
    在由Illustration 1所C图表的帮助下,q些有点儿神U的代码变得不那么秘了。该E序所构徏的归总v来就是一个用于指导底层数据库引擎的查询图(Query Graph)。descendҎ创徏了该囄一个分支,该分支向下步入对象的l构中。每个descendҎ在q个树中构徏一个结点,可以在这些结点上再附上一个约?使用constrainҎ)。用SQL的话来说Q约束指定了查询?WHERE"子句部分。多个约束可以在?and)或或(or)Ҏ的协助下l合h。在上面的查询中我们已经使用了andҎd联这些约束?br />                                     
与其它的查询方式一P查询l果q回到ObjectSet对象中,通过遍历该对象就可取出那些拿到的对象?br />     注意Q由于S.O.D.A.是一U低层次的访问方法,没有的指C,它就没有默认的行为。访问cases对象的成员变量result字段的代码很?br />     query.descend("cases").descend("result"). ...
我们q没有告诉S.O.D.A."cases"是一个集合对象。所以当查询执行Ӟ它会不被察觉地检ArrayList对象cases中所有元?TestCase对象)的result字段Q然后会正确地返回那些拥有符合搜索规范的试用例的测试组?br />
db4o性能调优
    我们已经展示了db4o的基本操?但无关紧要的删除操作除外Q下面将会提到它)。但Q正如我们在本文通篇所提到的,db4o发布(expose)了一个API层次l构Q以允许开发者能够选择以何U层ơ的APIL制徏立在该数据库引擎之上的应用程序。从另一斚w看,如果你所惛_的只是向数据库存入,及从数据库取出对象,那么你就已经看到了你所需要的一切。然而,如果你的应用的需求超ZdQ更斎ͼ查询和删除,可能q有一个db4o的特性可解决你的问题?br />     db4o的ObjectContainer实际上发?expose)了两个API。第一个API非常的简单,由十个方法组成。这些方法处理数据库的打开与关闭;dQ更斎ͼ查询和删除对象;及提交或中止事务。短a之,该APIZ提供了在操纵数据库时所需要所有功能。然而,该API中的一个方?-ext()--是进?被扩展的"ObjectContainer的一个入口。该被扩展的ObjectContainer为深入控制db4o的内部发?expose)了更多方法。例如,你可以获得ƈ改变数据库的配置上下文,使用它你能够修改该引擎的行ؓ?br />     例如Q假设你已经从数据库中拿C一个TestSuite对象Q发现该对象中的数据是错误的Qƈ军_该对象应该被删除。此外,你还军_你必d除的不仅是该TestSuite对象Q而且q有所有与之关联的TestCase对象(在ArrayList对象cases??br />     你是可以冗长而乏呛_遍历q个ArrayList对象Q一个接一个地删除每一个TestCase对象Q然后再删除TestSuite对象本n。可能一U更好的解决Ҏ是ؓq个TestSuite对象启用db4o?U联删除"Ҏ?br />     . . .
    // Fetch the database's configuration context
    Configuration config = db.ext().configure();
    // Get the ObjectClass for TestSuite
    ObjectClass oc = config.objectClass("testsuites.TestSuite");
    // Turn on cascaded delete
    oc.cascadeOnDelete(true);
    ...  ...
    db.delete(ts1);
    . . .
在上qC码中Q我们实例化了一个ObjectClass对象Q该对象使我们能够访问到TestSuite对象的db4o内部表现形式。我们打开cascadeOnDelete标记Q以便当执行db4o.delete(ts1)Ӟ不仅ts1对象会被删除Q而且所有由ts1引用的TestCase对象也会被删除?׃显而易见的原因Q默认情况下Q联删除是被关闭的)
    作ؓ另一个例子,假设你想为数据库预分配存储空_以至于要最化盘驱动器的头移?head movement)?最好是在硬盘碎片整理之后,q新创徏一个数据库时这样做?q且假设以ObjectContainer对象db作ؓ打开了的数据库:
    // Fetch the database's configuration context
    // 获得数据库的配置上下?br />     Configuration config = db.ext().configure();
    // Pre-allocate 200,000 bytes
    // 预分?00000000字节
    config.reserveStorageSpace(200000000L);
把数据库文g预扩展到200000000字节(略小?00兆字?。假设该盘已经做碎片整理了Q那么被分配的块是q箋的,q可显著提升数据库的讉K?br />
db4o高应用
    完全可以_db4o在它不大的空?U?00K)内已装入了够多的特性,相比较于db4o在运行过E中所做的众多事情Q我们不能花Ҏ多的W墨去解释它们了。但是有两个Ҏ十分突出,以至于肯定要提到它们?br />     db4o的对象复制实C被ȝ为面向对象版的数据库同步。用复制所提供的功能,你能Z个数据库中的一个对象做一个副本,q将该副本放入另一个数据库中。用这LҎQ副本对象就无Ş中和原始对象兌在了一赗对M对象--原始对象或副本对?-的改变都会被跟踪刎ͼ以便在之后的某个时候,数据库能够被重组Qƈ且这两个数据库中对象的不同之处可被分?例如Q可同步q两个数据库)?br />     它工作v来就像这PZ一个数据库可被复制Q与事务计数器一P该数据库中被创徏的Q何一个对象都用一个唯一全局标识W?UUID)q行了标记。当你从原始数据库中"复制"一个对象到另一个数据库中,副本对象会带着与它的原始对象相同的UUID和事务计数器。副本数据库现在可以从它的原始数据库那儿弄C。修改副本对象的内容会D对象的事务计数器被修攏V所以,当这两个数据库重新连接v来,db4o内徏的同步处理机制就能一个对象一个对象地q行正确的匹?使用UUID)Qƈ定原始或副本对象是否已l改变了。db4o甚至能追t到每个对象发生最后一ơ修Ҏ的时_以便用户写的冲突解决代码能确定哪个对象是最q更新的?br />     从操作行为来看,db4o的同步处理机制与原生查询十分怼。回想一下,当实C一个原生查询类Ӟ我们要定义一个matchҎQ该Ҏ定哪些对象W合(或不W合)查询规范。用同步复Ӟ我们要定义一个ReplicationProcess对象Q我们会把冲H处理对象传入该Ҏ中。这些Java代码可能像这P
    . . .
    ReplicationProcess replication = db1.ext().
        replicationBegin(db2, new ReplicationConflictHandler()
        {  
            public Object resolveConflict(
                ReplicationProcess rprocess, Object a, Object b)
                {
                    . . .  ...
                    return winning_object;
                }
            )
        };
在上qC码中QObject a是来自于数据库db1的对象,Object b则来自于数据库db2。默认情况下Q同步是双向的。同步处理保证胜出的对象(由resolveConflictҎq回的对?能存入这两个数据库中。所以当复制完成Ӟq两个数据库中被复制的对象就同步了?br />     最后,db4o最强大的特性之一是它能毫不费力地容忍类l构的演变。假设,在向数据库内加入数百个TestSuite对象之后Q我们决定这个类必须要被修改。就是说Q我们已l被告之Q该pȝ必须能追t到每个TestSuite的执行QA工程师,所以必d入如下字D?br />     private int engineerID;
到TestSuitecȝ定义中?br />     现在我们遇C两个相关联的问题。第一个问题不是很p糕Q已存在于数据库中的用于表示试的TestSuite对象Qƈ没有为它们记录QA工程师的IDQ所以我们将不得不将一个虚拟的Dl这些对象的engineerID字段Q该g指出"未记录QA工程师的ID"。第二个问题更隑ֺ付了Q我们必M知原因地把已有的TestSuite对象UL?新的"cȝ构中。我们必Mؓ数据库中所有已存在的TestSuite对象加上一个engineerID字段。除了把旧数据库中的对象复制C个中间性的文gQ然后重新创Z个数据库q种Ҏ之外Q我们还能怎么做呢Q?br />     q运地是Q用db4oQ我们确实什么都不用做。ؓ了能操纵新的engineerID字段Q以完成业务逻辑上所要求的变化,如果只是向(我们的应用程序中?TestSuitecL加一个engineerID字段Q我们完全不必触动db4o API的Q何调用。当db4o使用"新的"TestSuitecȝ构去d"旧的"TestSuite对象Qdb4o认些对象中的engineerID字段消失了,q且会优雅地把该字段的D?。如果我们把0当作"未记录QA工程师的ID"Q那么我们所做的UL完成了。写入到数据库中的新TestSuite对象会包括新字Dc?事实上,Ҏ的TestSuite对象本nq行重写Q会使db4o不被察觉Cؓq些对象加上新字Dc?所以,通过发布一个包含新的TestSuite定义的更新应用,我们完全可以不被察觉C旧的TestSuite对象UL到新?..正如前述应用所做的那样?br />
全方位数据库
    通过适当地应用,db4op成ؓ数据库中?瑞士军刀"。它占用_的内存I间Q它能够被包含在一个不需要消耗大量资源的目中。同样地Q一个数据库只在盘上占用一个文件的事实可能会Z在第一眼看到它Ӟ不能认识到它丰富的功能。将数据库从一个地方移到另一个地方就是一个简单的文g拯Q你不必担心分离的烦引文Ӟ数据文gQ数据库l构文g{等q些文g的位|。对于快速部|和零管理的数据库应用,db4o很能胜Q?br />     另外Q根据我们已多次描述q的Qdb4o在简单性和优雅之间辑ֈ了适度的^衡。db4o的QBE既如此的单,又如此的功能强大Q对于一lo人惊奇的应用Q它l常是我们唯一需要的查询API。如果你主要是通过指针D而不是查询去讉K数据库,QBEq别有吸引力。在q种情况下,QBEl常能高效地拿到一个对象网l?Object Network)的根对象。然后,你就能用db4o的激z?activation)功能从根部向下进行对象引用导航,如果q些对象都完全在内存中的话,你就更可以这么做了?br />     而在使用QBEq不高效的时候,原生查询和S.O.D.A.pz上用场了,q且它们伴随着一堆特性和低层ơ的API。我们还没有展示db4o的加密功能,插入式文件I/O(例如Q它允许你添?写后?read-after-write)"验证)Q信号量Q客L/服务器端模式Q以及其它难以计数的功能。我们结论性的很简单:当你的下一个Java应用需要一个数据库Q在最l开始编码之前,你可以去讉K一下http://www.db4objects.com/。这是很值得的?br />



Sha Jiang 2007-12-05 12:31 发表评论
]]>
Maven入门--较复杂的实例(?http://www.aygfsteel.com/jiangshachina/archive/2006/12/12/79093.htmlSha JiangSha JiangTue, 12 Dec 2006 10:03:00 GMThttp://www.aygfsteel.com/jiangshachina/archive/2006/12/12/79093.htmlhttp://www.aygfsteel.com/jiangshachina/comments/79093.htmlhttp://www.aygfsteel.com/jiangshachina/archive/2006/12/12/79093.html#Feedback18http://www.aygfsteel.com/jiangshachina/comments/commentRss/79093.htmlhttp://www.aygfsteel.com/jiangshachina/services/trackbacks/79093.htmlMaven入门--较复杂的实例
本文用一个较复杂的实例,讲述如何定制目录布局(即不使用Maven标准目录布局)Q以及讲qC些关键插件的使用(配置)。ؓ了方便其它朋友能够方便地使用该实例,后台数据库用开源的面向对象数据?-db4oQ该数据库无需安装Q已包含在与本文配套的实例中Q文末附有该实例的下载链接?2007.01.02最后更?
注:转蝲时请注明原作?jiangshachina)及出?http://www.aygfsteel.com/jiangshachina)Q?/span>

1 实例的构?/font>
文章开头的摘要已经讲述了,本文仍然以一个实例描q如何用MavenQ?/font> 该实例将使用非Maven标准的目录结构,q将呈现一些关键的Maven插g的配|与应用?/font> 该实例是一个基于db4o的数据库Web应用。该应用本n十分单,即从db4o数据库中查询q记录ƈ它们显现在Web面中?br />     该实例仍然由一个普通应用工E?demo-app)与一个Web应用工程(demo-web)Q以及这两个工程的父工程(demo)构成Q最l的目标是将Web应用工程制作成war文gQƈ部v到JBoss服务器中。启动服务器后,能够在页面中看到正确的查询结果?/font>
    该实例?font color="#008000">Eclipse3.2 + JDK1.5.0_10 + Windows2000开发。当然这仅仅只是我个人的开发^収ͼ但该实例q不受限于此q_Q由于我选择使用db4o针对JDK1.5的品包Q所以该实例只能q行在JDK1.5.0或更高版本的JDK/JRE中;
该工E中的所有文仉使用UTF-8~码方式?/font>

2 demo工程
demo工程是其它两个工E的父工E,它的主要职责是预定义子工E所需要依赖的jar文g(artifact)Q以及针对子工程所使用的插件进行通用配置。该工程完整的POM文g如下所C:
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>mvn.demo</groupId>
    <artifactId>demo</artifactId>
    <packaging>pom</packaging>
    <version>
1.0-SNAPSHOT</version>
    <description>Maven Demo Project</description>

    <modules>
        <module>demo-app</module>
        <module>demo-web</module>
    </modules>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>mvn.demo</groupId>
                <artifactId>demo-app</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>mvn.demo</groupId>
                <artifactId>demo-web</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>com.db4o</groupId>
                <artifactId>db4o-java5</artifactId>
                <version>
5.5</version>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>
2.4</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>commons-configuration</groupId>
                <artifactId>commons-configuration</artifactId>
                <version>
1.2</version>
                <exclusions>
                    <exclusion>
                        <groupId>dom4j</groupId>
                        <artifactId>dom4j</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>xml-apis</groupId>
                        <artifactId>xml-apis</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>xalan</groupId>
                        <artifactId>xalan</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>xerces</groupId>
                        <artifactId>xercesImpl</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
        <groupId>junit</groupId>
         <artifactId>junit</artifactId>
           <version>
3.8.1</version>
      <scope>test</scope>
    </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-
8</encoding>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>
1.5</source>
                    <target>
1.5</target>
                    <encoding>UTF-
8</encoding>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                    </archive>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <archive>
                        <addMavenDescriptor>false</addMavenDescriptor>
                    </archive>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-javadoc-plugin</artifactId>
                <configuration>
                    <charset>UTF16</charset>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
    预定义工E的依赖关系Q就是把会被子工E依赖的artifact的详l信?groupIdQartifactIdQversionQ?..)先声明到<dependencyManagement>中。然后子工程只需要声明用某个artifact可以了Q即那时只需要设|groupId和artifactId(甚至更少)可以了?/font> <dependencyManagement>中声明的artifactq不一定真的会被用到?/font>
2.1 声明依赖关系
    Ҏ实际情况Q?/font> 该实?/font> 需要用db4o针对java5的品包(jar文g)。由于该jar文gq不存在于Maven的中央仓库中Q所以我们不能直接通过Maven获得该jar文g。我们只能另外下载db4o-5.5(Java?的压~包Q然后从压羃包内获得db4o-java5.jar。得到该jar后,必须先将它安装到Maven的本C库中(安装Ҏ参见资源[1]Q主?向本C库安装文件时要生成POM文g")Q以备后面的使用。此处将该artifact的groupId定义?font color="#0000ff">com.db4oQartifactId定义?font color="#0000ff">db4o-java5Qversion自然是5.5?误上述POM脚本)?br />
    ׃该实例最l是一个Web应用Q所以它臛_需要依赖Servlet的包(servlet-api-2.4.jar)Q还需要commons-configuration-1.2.jar。这两个artifact都已l存在于Maven中央仓库中,所以我查找到它们后Q按照Maven中央仓库的命名将它们声明C<dependencyManagement>?误上述POM脚本)。junit是进行单元测试时使用的artifactQ?假设)它肯定会被每个工E用,所以没有将它设|到 <dependencyManagement>中,而直接设|到?/font> <dependency>中?/font>
    l心的朋友肯定已l发CQ针?/font> commons-configuration的依赖声明处多了一些语句。从表面上看Q应该是排除?个artifact(dom4jQ?/font> xml-apis Q?/font> xalan ?/font> xerces )。不错,是排除了这4个jar文g(artifact)。如果有兴趣的话Q可以将整个<exclusions>元素删除Q然后再试一下制作war文g。你会发现在WEB-INF/lib目录下存在着q?个artifact对应的jar文g。那我ؓ什么要它?#8220;排除”呢?因ؓQ它们是多余的!卻I它们对于我的q个Web应用来说Q根本就是无用的Q?br />     Maven2加入了一个很好的Ҏ:自动加蝲“依赖的依?Transitive Dependency)”。以commons-configurationZ。ؓ了能够让它运行正常,我们实际上还需要其它一些jar(artifact)Q如commons-collectionsQcommons-langQ?..。但q些artifact我都没有“昄”地声明需要依赖它们,但Maven会自动加载,因ؓ commons-configuration的POM文g它们声明ؓ了dependency ?br />     既然那个4个artifact?font size="2">commons-configuration的依赖,Z么会认ؓ它们是无用的呢?实际上,它们׃应该被声明到commons-configuration的依赖关pM。这?/font>commons-configuration开发者的pQ他们没有将依赖关系整理清晰Q而将一些确实既不是runtimeQ更不是compile-time需要的artifact攑օC依赖关系中。在Maven中央仓库中存在着很多q种情况Q所以我们有旉要弄清楚“哪些文g是我们真正需要的Q哪些是可以被清除的”。但有时候,很难做到一个不漏。正是由于这一原因Q自动加载Transitive Dependencyq一极好的特性,有时让h十分无奈 ^_^
2.2 Ҏ件进行基本配|?/strong>
我们可以把对插g的全局?如针Ҏ个项目的)讄攑ֈ较高层次的POM文g中,因ؓ它们被设|后Q子工程们就会自焉守它们,而且可以使每个子工程的情况都是一L?br />     在第1节中Q已l表明该工程使用JDK1.5q_Qƈ且所有文仉使用UTF-8
的编码方?/font>。而Maven默认使用JDK1.3U别的javac~译器;默认使用本地~码方式(体中文Windows操作pȝ默认使用GBK~码方式)处理文g。这样就必须对Mavenq行适当讄Q以满工程的实际需要?br />     针对资源文g的处?font color="#000000">QMaven使用maven-resources-plugin插gQ需要将它的~码方式讄为UTF-8。编译Java源文Ӟ是用maven-compiler-plugin插gQ需要将它的source(Java源文?与target(class文g)的别都讄?.5Q另外还要将它的encoding方式讄为UTF-8。(详细讄误POM脚本Q?/font>

3 demo-app工程
demo-app工程是一个普通应用程序工E,它用于处理和数据库相关的操作Q如针对数据库的增、删、改、查{基本功能。该工程POM文g的主要内容如下所C:
<project>
    ......

    <build>
        <finalName>app</finalName>
        <directory>target</directory>

        <sourceDirectory>src/java</sourceDirectory>
        <outputDirectory>target/classes</outputDirectory>
        <resources>
            <resource>
                <directory>src/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </resource>
        </resources>

        <testSourceDirectory>src/test/java</testSourceDirectory>
        <testOutputDirectory>target/test-classes</testOutputDirectory>
        <testResources>
            <testResource>
                <directory>src/test/java</directory>
                <excludes>
                    <exclude>**/*.java</exclude>
                </excludes>
            </testResource>
        </testResources>
    </build>
</project>
    文章的开头已l提刎ͼ本实例将会用定制的目录l构Q但在前面却一字不提此事,现在描q如何定制目录结构。Maven的标准目录结构其实是在Super POM中设|的Q由于Q何POM都会l承该POMQ所以所有的工作都会默认使用标准目录l构。要定制目录Q其实就是需要重新设|相兛_数的|即用新D盖Super POM中的倹{?br />
[1]<finalName>Q该元素指定了工E输出的artifact的名Uͼ默认gؓ${artifactId}-${version}Q此处修改ؓapp?br /> [2]<directory>Q该元素指定了工E输出的目标目录。默认gؓtargetQ此处未修改变?br /> [3]<sourceDirectory>Q该元素指定了Java源文件所在的目录。默认gؓsrc/main/javaQ此处修改ؓsrc/java?br /> [4]<outputDirectory>Q该元素指定了编译后的class文g的放|目录。默认gؓtarget/classesQ此处未作改变?br /> [5]<resources> <resource>Q该元素指定了Java源文件用的资源文g的存攄录。默认gؓsrc/main/resourcesQ此处修改ؓsrc/java。由于在~码Java源文件时QMaven会将资源路径中的文g全部拯到classes目录。而此时将Java资源文g目录与Java源文件目录,讄为同一目录Q所以需要将.java文g排除在资源文件的范畴之外( <exclude>**/*.java</exclude> )?br /> [6] <testSourceDirectory>Q该元素指定了单元测试Java源文件的攄目录。默认gؓsrc/test/javaQ此处未作修攏V?br /> [7] <testOutputDirectory>Q该元素指定了单元测试Java源文件编译后的class文g攄目录。默认gؓ target/test-classesQ此处未作改变?br /> [8] <testResources> <testResource>Q该元素指定了单元测试Java源文件所使用的资源文件的攄目录。默认gؓsrc/test/resourcesQ此处修改ؓ src/test/java。ƈ且也做了?/span> 讄<resources> <resource>时相同的处理(排除Java源文??br />     通过上述讄后,可以拥有一个定制的Maven工程目录l构了?br />
4 demo-web工程
demo-web工程是整个应用最l的目标输出Q因为此处的目的是制作一个war文gQ然后将它部|到JBoss服务器中。与demo-app工程相比Qdemo-web工程的POM文g主要有如下不同内容:
<project >
    ......
    <build>
        ......
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>
2.0.1 </version>
                <configuration>
                    <webappDirectory>target/${artifactId}</webappDirectory>
                    <warSourceDirectory>src/webapp</warSourceDirectory>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jboss-maven-plugin</artifactId>
                <version>
1.3.1 </version>
                <configuration>
                    <jbossHome>E:/jboss-
4.0.2 </jbossHome>
                    <serverName>default</serverName>
                    <fileName>
                        ${project.build.directory}/${project.build.finalName}.${project.packaging}
                    </fileName>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
可以看出不同之处在于对maven-war-plguin及jboss-maven-plugin插g的配|与使用?br />     Maven使用maven-war-plugin插g对Web工程制作war文g。由于本文用了定制目录l构Q这样则会maven-war-plugin无法扑ֈWeb工程的Web Root目录(默认是src/main/webapp)Q所以需要对该插件进行适当地配|?lt;warSourceDirectory>是Web工程的Web Root目录Q此处设|ؓQ?lt;webappDirectory>是制作war文g之前Q相当于是一个被打开(exploded)的war文g的根目录(默认是target/artifactId-version)?br />     该工E的脚本中,q用了一个JBoss插g。该插g可以制作好的war文g部v(实质上是拯)到指定的JBoss部v目录中?lt;jbossHome>是JBoss的安装根目录Q?lt;serverName>指JBoss Server的名Uͼ<fileName>是被部vwar文g的名U?br />
参考资?/strong>
[1]Maven入门--概念与实? http://www.aygfsteel.com/jiangshachina/archive/2006/09/01/67080.html
[2]Maven + Continuum Weed. http://www.aygfsteel.com/jiangshachina/archive/2006/09/11/68944.aspx
[3]Maven POM Reference. http://maven.apache.org/pom.html
[3]db4o. http://www.db4objects.com
本文实例下蝲地址--http://www.aygfsteel.com/files/jiangshachina/mvn-demo.rar



Sha Jiang 2006-12-12 18:03 发表评论
]]>
վ֩ģ壺 | Դ| | | | Ҧ| | | | | ˴| ¡| | Խ| Ѯ| ī񹤿| | | | ½| | ߴ| | | | | | ͬ| Ӽ| ų| ӱʡ| | | | | | | Դ| ¡| Ǹ| |