﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Jiangshachina-随笔分类-Database</title><link>http://www.blogjava.net/jiangshachina/category/16091.html</link><description>同是Java爱好者，相逢何必曾相识！&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;a cup of Java, cheers!</description><language>zh-cn</language><lastBuildDate>Fri, 10 Jul 2015 09:35:43 GMT</lastBuildDate><pubDate>Fri, 10 Jul 2015 09:35:43 GMT</pubDate><ttl>60</ttl><item><title>MySQL: MyISAM or InnoDB?(译)</title><link>http://www.blogjava.net/jiangshachina/archive/2009/05/31/279288.html</link><dc:creator>Sha Jiang</dc:creator><author>Sha Jiang</author><pubDate>Sun, 31 May 2009 13:41:00 GMT</pubDate><guid>http://www.blogjava.net/jiangshachina/archive/2009/05/31/279288.html</guid><wfw:comment>http://www.blogjava.net/jiangshachina/comments/279288.html</wfw:comment><comments>http://www.blogjava.net/jiangshachina/archive/2009/05/31/279288.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangshachina/comments/commentRss/279288.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangshachina/services/trackbacks/279288.html</trackback:ping><description><![CDATA[<div align="center"><strong><span style="font-size: 10pt;"><span style="font-size: 14pt;">MySQL: MyISAM or InnoDB?</span></span></strong><br />
</div>
<span style="font-size: 10pt;">
通过<a href="http://www.dzone.com/links/index.html">JavaLobby</a>看到的一篇<a href="http://blog.inetu.net/2009/04/mysql-innodb-or-myisam/">博文</a>，为选择MySQL的数据表引擎提供了一些意见，希望对大家有帮助。(2009.05.31最后更新)<br />
<strong><span style="color: red;">我这个可爱的小哥哥祝可爱的小朋友们节日愉快 ^_^</span></strong><br />
<br />
&nbsp;&nbsp;&nbsp; MyISAM是MySQL的默认存储引擎，但很多人忘记还有其它的选择。决定使用哪种(哪些)存储引擎可能需要些技巧，但评估一下MyISAM是否适合你的需要还是值得的。有一组存储引擎可用，但我将只关注MyISAM和InnoDB，因为它们被用的最多。<br />
需考虑的问题：<br />
&nbsp;&nbsp;&nbsp; 你是否需要外键？<br />
&nbsp;&nbsp;&nbsp; 你是否需要事务？<br />
&nbsp;&nbsp;&nbsp; 你是否需要全文索引？<br />
&nbsp;&nbsp;&nbsp; 你的数据访问(查询)模式是什么？<br />
&nbsp;&nbsp;&nbsp; 你的数据集有多大？<br />
<br />
&nbsp;&nbsp;&nbsp; 思考上述问题将使你走入正确的方向，但有些例外。如果你使用事务或外键，就使用InnoDB。要使用全文索引，你常需选择MyISAM，因为它内建地支持这一特性；但是，MyISAM难以应对超过200万的数据行。你可以使用Sphinx以使你的InnoDB表能获取全文索引，但这需要花费一些时间。<br />
&nbsp;&nbsp;&nbsp; 数据集的大小是决定你使用哪种引擎的主要因素。由于InnoDB的事务和崩溃恢复特性，对于较大的数据集，则倾向于该引擎。然而，恢复MyISAM数据表所花费的时间由数据集的大小来衡量，但恢复InnoDB所花费的时间由事务日志的大小来衡量-而你对日志有一定的控制力。例如，相较于恢复 InnoDB数据表所需要的几分钟，你可能需要几小时甚至几天时间来恢复MyISAM数据表。<br />
&nbsp;&nbsp;&nbsp; 你读/写数据表的方式可能会极大地影响你所使用的存储引擎的性能。在MyISAM数据表中执行COUNT()会很快，但对于InnoDB数据表则十分痛苦，最好避免。在InnoDB数据表中查找主键极其的快，但要注意到，太长的主键会影响到性能。批量插入在MyISAM数据表更快些，但批量更新在 InnoDB中会较快些--特别是当进行并发增加时。<br />
&nbsp;&nbsp;&nbsp; 那么你应该选择哪种引擎呢？如果你工作在一个小项目中，那么MyISAM可能正适合你。甚至在较大环境中使用MyISAM也能获取很大的成功，但这依具体情况不同而不同。如果你计划用于非常大的数据集，并且需要事务或外键约束，那就应该直接使用InnoDB。但需要记住，相较于MyISAM，InnoDB 数据表需要很大的内存和存储空间。将100GB的MyISAM数据表转化成InnoDB数据表就会表现得令人吃惊的坏。<br />
<br />
</span>
<img src ="http://www.blogjava.net/jiangshachina/aggbug/279288.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangshachina/" target="_blank">Sha Jiang</a> 2009-05-31 21:41 <a href="http://www.blogjava.net/jiangshachina/archive/2009/05/31/279288.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>深入db4o(译)</title><link>http://www.blogjava.net/jiangshachina/archive/2007/12/05/164430.html</link><dc:creator>Sha Jiang</dc:creator><author>Sha Jiang</author><pubDate>Wed, 05 Dec 2007 04:31:00 GMT</pubDate><guid>http://www.blogjava.net/jiangshachina/archive/2007/12/05/164430.html</guid><wfw:comment>http://www.blogjava.net/jiangshachina/comments/164430.html</wfw:comment><comments>http://www.blogjava.net/jiangshachina/archive/2007/12/05/164430.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangshachina/comments/commentRss/164430.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangshachina/services/trackbacks/164430.html</trackback:ping><description><![CDATA[<div align="center"><strong><span style="font-size: 10pt;"><span style="font-size: 14pt;">深入db4o<span style="font-size: 10pt;"><span style="font-size: 8pt;"><strong><span style="font-size: 10pt;"><span style="font-size: 14pt;"><span style="font-size: 10pt;"><strong><span style="font-size: 10pt;"><span style="font-size: 14pt;"><span style="font-size: 10pt;"><span style="font-size: 8pt;"><strong><span style="font-size: 10pt;"><span style="font-size: 14pt;"><span style="font-size: 10pt;"><span style="font-size: 10pt;"><span style="font-size: 12pt;"><span style="font-size: 10pt;"><br />
</span></span></span></span></span></span></strong></span></span></span></span></strong></span></span></span></strong></span></span></span></span></strong>
</div>
<span style="font-size: 10pt;">&nbsp;&nbsp;&nbsp; 这是Rick Grehan发表在</span><span style="font-size: 10pt;"><a href="http://www.theserverside.com/">TheServerSide</a>上的<a href="http://www.theserverside.com/tt/articles/article.tss?l=Insidedb4o"><span style="font-size: 10pt;">一篇关于面向对象数据库--db4o</span><span style="font-size: 10pt;">的文章</span></a></span><span style="font-size: 10pt;">，较全面地介绍了<a href="http://www.db4o.com/">db4o</a>的关键特性，希望对大家认识<a href="http://www.db4o.com/">db4o</a>能有所帮助。(2007.12.07最后更新)</span><span style="font-size: 10pt;"><br />
<br />
&nbsp;&nbsp;&nbsp; db4o-<em>针对对象的数据库</em>-是一个完全的对象数据库；它以使对象在其生命周期中-无论是在数据库内或是在外-都保持着它们的本性这样一种方式操纵对象。不论类的复杂性如何，对象的内容，结构和关系都能够被保存。<br />
&nbsp;&nbsp;&nbsp; 更准确地说，db4o是一个数据库引擎，你只要将它的一个jar文件包含到你的数据库应用的类路径中就可以使用它了(至少对于Java是这样的)。所以，db4o运行在与你的应用程序相同的进程空间中，并能被直接地调用；它不需要类似于在ODBC或JDBC中使用的驱动文件。db4o存在针对Java，.NET和Mono的版本；它们在功能上都彼此相等。(事实上，使用.NET创建的db4o数据库也能由Java程序访问；反之亦然。)<br />
&nbsp;&nbsp;&nbsp; db4o是开源的。可执行文件，源代码和文档可从http://www.db4objects.com/中下载。广泛的例子程序，和一个活跃的用户社区一样，也都可以从这个站点中找到。<br />
&nbsp;&nbsp;&nbsp; db4o最引人的特性之一就是它在简易性与强大的功能之间的显著平衡。一方面，它的API是如此地易于掌握和方便使用，即使是初学者也能在相同的时间内创建一个功能完备的数据库对象。另一方面，这些相同的API也提供了更底层的能够深入调用数据库引擎的方法，以允许核心开发者为了得到适当的性能而能深入到该引擎的内部中去调整db4o的工具。<br />
&nbsp;&nbsp;&nbsp; db4o的特性就是最好的证明--这胜过只是讨论--所以我们将通过示例这种方法去证明db4o。然而，我们必须牢记本文通篇只是展示了db4o特性中的一部分罢了。感兴趣的朋友会发现为了知晓该数据库引擎的全部功能而去查阅db4o的文档所花的时间是值得的。<br />
<br />
<strong><span style="font-size: 12pt;">
db4o基础</span></strong><br />
&nbsp;&nbsp;&nbsp; 让我们以初学者使用db4o时可能会做的事情开始：定义了一些类，然后持久化这些类的对象。我们所假定的类为同样也是假定的QA项目做一个跟踪测试的系统。我们的系统由两个类组成，首先是TestSuite类：<br />
&nbsp;&nbsp;&nbsp; public class TestSuite {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private String name;&nbsp; // Test Suite name<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private String description;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private String configuration;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private char overallScore;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private ArrayList &lt;TestCase&gt; cases;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private long dateExec;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... &lt;remainder of TestSuite definition&gt; ...<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; TestSuite是TestCase对象的容器，(一个测试用例就是一个可单独执行的测试程序--相关的测试用例组合成一个测试组)。测试组使用额外的，全局的数据成员，每个数据成员的用途也是相对明显的：configuration记录被测试的指定系统；overallScore是对整个测试组一个简要的评分('P'代表通过，'F'代表失败，'B'代表被阻塞，等等。)；dateExec是一个毫秒级的域，标识该测试组被执行时的日期与时刻。是ArrayList对象的cases含有单个的测试用例，由TestCase类定义：<br />
&nbsp;&nbsp;&nbsp; public class TestCase {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private String name;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private String comment;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private char status;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private long duration;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private float result;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... &lt;remainder of TestCase definition&gt; ...<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; 每个测试用例都有一个名称，形式自由的注释字段，状态(通过或失败)，持续时间和结果(例如，为了与测试-字节/秒的吞吐量-的任意数据关联)。<br />
&nbsp;&nbsp;&nbsp; 因为我们所关注是db4o的使用，所以我们不想在描述这些类的使用细节上停留。就让我们简单地说，我们已经执行了一个特别地测试组中所有的测试用例，将测试的结果存放在一个TestSuite对象中(与TestCase对象相关的ArrayList对象cases中)，然后关闭数据库。是不是太容易了。<br />
&nbsp;&nbsp;&nbsp; // Create the database<br />
&nbsp;&nbsp;&nbsp; new File("testsuites.YAP").delete();<br />
&nbsp;&nbsp;&nbsp; ObjectContainer db = Db4o.openFile("testsuites.YAP");<br />
&nbsp;&nbsp;&nbsp; // Store the TestSuite object<br />
&nbsp;&nbsp;&nbsp; db.set(testsuite);<br />
&nbsp;&nbsp;&nbsp; // Close the database<br />
&nbsp;&nbsp;&nbsp; db.close();<br />
&nbsp;&nbsp;&nbsp; 就是它。弹指一挥间，你就已经做到了。(当然，为了保持简洁，我们去掉了创建TestSuite对象和它的TestCase组件的细节)<br />
&nbsp;&nbsp;&nbsp; 停下来想想上述代码做了什么事情。特别要考虑你没有看到的--db4o已经做了但还未被告之的事情。<br />
&nbsp;&nbsp;&nbsp; 首先，我们不需要告诉db4o任何关于TestSuite类的结构的信息；不需要我们的帮助，db4o就能发现这个结构。利用Java反射机制的能力，db4o测定TestSuite类的结构，并勾勒出该类的装配方式以推导出此类对象的成员与关键数据。<br />
&nbsp;&nbsp;&nbsp; 第二，我们不必建议db4o去关注ArrayList。不仅我们不必将ArrayList的大小告诉db4o，而且我们也不必把它里面的内容告诉db4o。正如db4o在它刚接触testsuite对象时就能够发现它所需要的一切，db4o也能知道它所需要的关于(在ArrayList中的)TestCase对象的所有信息。<br />
&nbsp;&nbsp;&nbsp; 结果就是，如果我们把testsuite作为一个任意宠大而复杂的对象树的根，db4o能找到并存储整个树而不需要我们的任何协助。所以，存储这个处于根部的对象testsuite也就是存储了整个ArrayList对象。<br />
&nbsp;&nbsp;&nbsp; 最后，我们也没有必须要求db4o以事务的保护性方式去调用set方法。任何会修改ObjectContainer(表示数据库的db4o对象)的调用都会自动地开启一个事务，除非已经有一个活跃的事务了。此外还会调用close方法去终止这个事务，所以上述代码等价于：<br />
&nbsp;&nbsp;&nbsp; db.startTransaction();<br />
&nbsp;&nbsp;&nbsp; db.set(testsuite);<br />
&nbsp;&nbsp;&nbsp; db.commitTransaction();<br />
&nbsp;&nbsp;&nbsp; db.close();<br />
&nbsp;&nbsp;&nbsp; 此处的startTransaction和commitTransaction方法是为了证明我们的观点而虚构的。db4o也确实有显示地提交或中止事务的方法，但为了使原先的代码足够的简洁我们没有使用这些方法。db4o隐式的事务使得数据库能够一直处于一致的状态；一旦commit方法已经执行了，数据库的完整性就能够得到保证，甚至是发生了灾难性失败也能如此。<br />
<br />
<strong><span style="font-size: 12pt;">
查询I - QBE</span></strong><br />
&nbsp;&nbsp;&nbsp; 有了已经存于数据库中的对象，下一步我们想要展示的操作将肯定就是查询和恢复。db4o提供了三种查询API：有一种简单，有一种优雅，还有一种则复杂。每一种API都有其所长，并适用于不同的查询条件。以db4o的眼光来看，你选择哪一种API并没有关系：它们都是可兼容的。<br />
&nbsp;&nbsp;&nbsp; 我们以简单的API开始：query by exampel(QBE)。<br />
&nbsp;&nbsp;&nbsp; 使用QBE是如此的容易：为你的查询目标构建一个'模板'对象，然后把它传入ObjectContainer的query方法。实际上，你就是告诉db4o'去拿到所有与这个对象看起来一样的对象'。(这与JavaSpaces查询API非常相似；为了清楚地了解如何处理基本数据类型，可以看下面的内容，db4o的处理方式与JavaSpaces不同。也要注意，JavaSpace Entry对象期望使用public字段，db4o则没有这种要求。)<br />
&nbsp;&nbsp;&nbsp; 假设一个测试组名为"Network Throughput"，我们想取出这个测试组执行的所有测试以便我们能确定失败了的测试所占的百分比(基于TestSuite的overalScore值)。使用QBE，完成该工作的代码如下：<br />
&nbsp;&nbsp;&nbsp; // Open the database<br />
&nbsp;&nbsp;&nbsp; ObjectContainer db = Db4o.openFile("testsuites.YAP");<br />
<br />
&nbsp;&nbsp;&nbsp; // Instantiate the template object, filling in<br />
&nbsp;&nbsp;&nbsp; // only the name field<br />
&nbsp;&nbsp;&nbsp; testTemplate = new TestSuite("Network Throughput");<br />
<br />
&nbsp;&nbsp;&nbsp; // Execute the query<br />
&nbsp;&nbsp;&nbsp; ObjectSet result = db.get(testTemplate);<br />
&nbsp;&nbsp;&nbsp; fails = 0.0f;<br />
&nbsp;&nbsp;&nbsp; total = 0.0f;<br />
<br />
&nbsp;&nbsp;&nbsp; // Step through results,<br />
&nbsp;&nbsp;&nbsp; while(result.hasNext())<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testsuite = (TestSuite)result.next();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(testsuite.getOverallScore()=='F')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fails += 1.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total += 1.0f;<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; if(total == 0.0f)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("No tests of that type found.");<br />
&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Percent failed: " + (fails/total * 100.0f) + "%");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("Total executed: " + total);<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; db.close();<br />
&nbsp;&nbsp;&nbsp; 在上面的代码中，testTemplate是QBE的模板对象。注意，只有它的name字段有真实的值；所有其它的成员变量不是为null就是为0。Null或0字段不参与QBE查询；因此，调用db.get方法就会返回在该数据库中name字段匹配"Network Throughput"的所有TestSuite对象。匹配的TestSuite对象将返回在一个ObjectSet结果对象中。上述代码遍历该结果，取出对象，然后计算结果并展示出来。<br />
&nbsp;&nbsp;&nbsp; QBE明显的优点就是它的简易性。不需要掌握其它单独的查询语言。另外，QBE也是类型安全的：你不需要创建一个类似于SQL的查询语句<br />
&nbsp;&nbsp;&nbsp; SELECT TestSuite.overallScore FROM TestSuite WHERE TestSuite.name = 200.0<br />
&nbsp;&nbsp;&nbsp; 另一方面，由于该查询是由Java代码创建的，编译器不会允许你把一个浮点值赋给一个String字段；反之亦然。<br />
&nbsp;&nbsp;&nbsp; QBE明显的缺点就是它只能执行"等于"查询。另外，QBE使用null值去确定不参与查询的String或对象引用成员变量，使用0值去指定不参与查询的数字字段。所以，例如，我不能发明一个QBE查询去获得所有result字段的值为0的TestCase对象。<br />
&nbsp;&nbsp;&nbsp; 更为精细的查询要求一个能力更强的查询机制，而db4o恰恰就有这样一种机制。<br />
<br />
<span style="font-size: 10pt;"><span style="font-size: 10pt;">
</span><strong><span style="font-size: 12pt;">
查询方式II - 原生查询(Native Query)</span></strong><br />
&nbsp;&nbsp;&nbsp; db4o的原生查询系统应该是能想像得到的最具弹性的查询机制。不像使用数据库查询语言去构建查询，你是使用"无格式的普通Java语句"去构造原生查询。原生查询用两种手段去实现这件不可思意的工作：一个是Predicate类；另一个是QueryComparator接口。这个类包含一个可重载的(overrideable)回调方法，该方法将指定如何从数据库中选择对象(如果你愿意，你将会看到查询语句的主体....)。这个接口只声明了一个方法，该方法用于指明如何对查询结果进行排序。<br />
&nbsp;&nbsp;&nbsp; 作为一个例子，我们假设想找到在给定的一周内执行过了的总得分为"failed"，但与之关联的测试用例中有超过一半的被评为"passed"的测试组。这不是一个简单的"等于"查询，所以它不能使用QBE构建。<br />
&nbsp;&nbsp;&nbsp; 然而，db4o的原生查询可以直接地生成该查询。首先，我们继承db4o的Predicate类：<br />
&nbsp;&nbsp;&nbsp; // Predicate class sub-class for native query example<br />
&nbsp;&nbsp;&nbsp; public class NativeQueryQuery extends Predicate&lt;TestSuite&gt;<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ObjectContainer db;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private long startdate;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private long enddate;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 构造器要在本地获得ObjectContainer对象和日期范围<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public NativeQueryQuery(ObjectContainer _db,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long _start, long _end)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; db = _db;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startdate = _start;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enddate = _end;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 这就是查询的主体<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public boolean match(TestSuite testsuite)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float passed;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; float total;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TestCase testcase;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 判断testsuite是否在指定的日期范围内<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(testsuite.getDateExec()&lt;startdate ||<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testsuite.getDateExec()&gt;enddate) return false;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 如果该测试组对象中没有测试用例对象，则拒绝将该测试组对象放入查询结果中<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(testsuite.getNumberOfCases()==0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return false;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 检查该测试组对象中的测试用例的通过率是否超过50%<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; passed = 0.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total = 0.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0; i&lt;testsuite.getNumberOfCases(); i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testcase = testsuite.getTestCase(i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(testcase.getStatus()=='P')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; passed+=1.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total+=1.0f;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if((passed/total)&lt;.5) return false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; 注意在这个类的使用中使用了Java泛型语义，这就是告诉db4o只去取TestSuite对象。当查询执行时，TestSuite对象就会传入match方法(我们之前提到过的回调方法)，如果传入的TestSuite对象符合查询规范该方法就返回true，否则就返回false。<br />
&nbsp;&nbsp;&nbsp; match方法中的代码首先确定侯选对象是否是在一周的日期范围内。如果是，则循环该对象中的成员变量测试用例的对象，计算出所有通过了的测试用例的总数。如果，得到的通过率小于50%，该测试组就被拒绝；否则，就让它通过。<br />
&nbsp;&nbsp;&nbsp; 我们可以使用如下的代码准确地展示该查询程序：<br />
&nbsp;&nbsp;&nbsp; . . .<br />
&nbsp;&nbsp;&nbsp; TestSuite testsuite;<br />
&nbsp;&nbsp;&nbsp; NativeQueryQuery nqqClass;<br />
&nbsp;&nbsp;&nbsp; Date now;<br />
<br />
&nbsp;&nbsp;&nbsp; // Open the database<br />
&nbsp;&nbsp;&nbsp; ObjectContainer db = Db4o.openFile("testsuites.YAP");<br />
<br />
&nbsp;&nbsp;&nbsp; // Instantiate a NativeQueryQuery object,<br />
&nbsp;&nbsp;&nbsp; // setting the start and end dates for<br />
&nbsp;&nbsp;&nbsp; // any test in the past week<br />
&nbsp;&nbsp;&nbsp; // 604800000 = milliseconds in a week<br />
&nbsp;&nbsp;&nbsp; now = new Date();<br />
&nbsp;&nbsp;&nbsp; nqqClass = new NativeQueryQuery(db,<br />
&nbsp;&nbsp;&nbsp; now.getTime()-604800000L,<br />
&nbsp;&nbsp;&nbsp; now.getTime());<br />
<br />
&nbsp;&nbsp;&nbsp; // Execute the query and display the<br />
&nbsp;&nbsp;&nbsp; // results<br />
&nbsp;&nbsp;&nbsp; System.out.println("Results:");<br />
&nbsp;&nbsp;&nbsp; ObjectSet results = db.query(nqqClass);<br />
&nbsp;&nbsp;&nbsp; if(results.isEmpty())<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("&nbsp; NOTHING TO DISPLAY");<br />
<br />
&nbsp;&nbsp;&nbsp; while(results.hasNext())<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testsuite = (TestSuite)(results.next());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(testsuite.toString());<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; db.close();<br />
&nbsp;&nbsp;&nbsp; . . .<br />
&nbsp;&nbsp;&nbsp; 可以把原生查询想像成这样：目标类的对象一个接一个从数据库中取出，然后把它们传入match方法中。只有那些被match方法返回true的对象才会置于查询结果ObjectSet对象中。基本上可以说，如果你会知道如何写Java代码，那么你就知道如何写原生查询。<br />
&nbsp;&nbsp;&nbsp; 那么排序呢？如果想按日期的升序排列查询结果，我们就要实现QueryComparator接口，如下所示：<br />
&nbsp;&nbsp;&nbsp;
public class NativeQuerySort implements QueryComparator&lt;TestSuite&gt;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int compare(TestSuite t1, TestSuite t2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (t1.getDateExec() &lt; t2.getDateExec()) return -1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (t1.getDateExec() &gt; t2.getDateExec()) return 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;
}<br />
compare方法的作用十分明显。那些在查询中得以胜出的对象会成对的传入compare方法，如果第一个对象会排在第二个对象之前，相同或之后的位置，该方法就会分别返回一个小于，等于或大于0的值。为了准确地说明对查询结果的排序，我们实例化NativeQuerySort，并把对query方法的调用修改成如下：<br />
&nbsp;&nbsp;&nbsp; . . .<br />
&nbsp;&nbsp;&nbsp; // Instantiate the sort class<br />
&nbsp;&nbsp;&nbsp; nqsClass = new NativeQuerySort();<br />
&nbsp;&nbsp;&nbsp; . . .<br />
&nbsp;&nbsp;&nbsp; ObjectSet results = db.query(nqqClass, nqsClass);<br />
&nbsp;&nbsp;&nbsp; . . .<br />
其它的代码仍然与原先的保持一致。<br />
&nbsp;&nbsp;&nbsp; 好怀疑的读者可能会抱怨道，原生查询只是一种编程上的小伎俩--相比较于直接去拿到所有的TestSuite对象然后再排除其中不符合条件的对象这样的程序，原生查询并不快。<br />
&nbsp;&nbsp;&nbsp;
是的，但并不十分准确。原生能够被优化。你所需要做的只是把两个jar文件--db4o-xxx-nqopt.jar(xxx表示db4o的版本)和bloat.jar--置于CLASSPATH环境变量中。在查询执行的时候，这些类库中的代码会对(在match方法中)例如基本数据类型比较，算术和布尔表达式，简单的对象成员访问，以及更多方面的结构进行优化。这个被支持的优化的列表在不停的增长，因为db4o引擎还在扩展优化的范围。<br />
<br />
<strong><span style="font-size: 12pt;">
查询方式III - S.O.D.A.</span></strong><br />
&nbsp;&nbsp;&nbsp; db4o独一无二的能力之一就是它的API被分层了。开发者能够选择通过高层次--赋予数据库引擎相当大的自由度，让它决定如何去实现它的操作--或者开发者也可以使用一种更直接地方式去访问db4o。后一种选择为程序员平添了更多的负担，程序员必须更加小心地引导数据库引擎的内部工作。但回报就是得到一个更快，能力更强的数据库应用。<br />
&nbsp;&nbsp;&nbsp; db4o的S.O.D.A.(Simple Object Data Access)查询机制就是该层次API的一个完美的例子。S.O.D.A.就是db4o的内部查询系统--QBE和原生查询都被翻译成了S.O.D.A.。然而，应用程序也能直接地调用S.O.D.A.。<br />
&nbsp;&nbsp;&nbsp; 假设我们想找到所有名为"Network Throughput"，且至少拥有一个其result字段--我们使用这个参数作为字节/秒的量度--不小于指定值(比方说，100)的测试用例的测试组。为该请求而做的S.O.D.A.查询可能就像这样：<br />
&nbsp;&nbsp;&nbsp; . . .<br />
&nbsp;&nbsp;&nbsp; TestSuite testsuite;<br />
<br />
&nbsp;&nbsp;&nbsp; // Open the database<br />
&nbsp;&nbsp;&nbsp; ObjectContainer db = Db4o.openFile("testsuites.YAP");<br />
<br />
&nbsp;&nbsp;&nbsp; // Construct the query<br />
&nbsp;&nbsp;&nbsp; Query query = db.query();<br />
&nbsp;&nbsp;&nbsp; query.constrain(TestSuite.class);<br />
&nbsp;&nbsp;&nbsp; Constraint nameConst = query.descend("name").<br />
&nbsp;&nbsp;&nbsp; constrain("Network Throughput");<br />
&nbsp;&nbsp;&nbsp; query.descend("cases").descend("result").<br />
&nbsp;&nbsp;&nbsp; constrain(100.0f).smaller().and(nameConst);<br />
<br />
&nbsp;&nbsp;&nbsp; System.out.println("Results:");<br />
&nbsp;&nbsp;&nbsp; // Execute the query<br />
&nbsp;&nbsp;&nbsp; ObjectSet result = query.execute();<br />
&nbsp;&nbsp;&nbsp; if(result.isEmpty())<br />
&nbsp;&nbsp;&nbsp; System.out.println("NOTHING TO DISPLAY");<br />
<br />
&nbsp;&nbsp;&nbsp; while(result.hasNext())<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; testsuite = (TestSuite)(result.next());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(testsuite.toString());<br />
&nbsp;&nbsp;&nbsp; }<br />
<br />
&nbsp;&nbsp;&nbsp; db.close();<br />
&nbsp;&nbsp;&nbsp; . . .<br />
&nbsp;&nbsp;&nbsp; 在由Illustration 1所示图表的帮助下，这些有点儿神秘的代码就变得不那么神秘了。该程序所构建的归总起来就是一个用于指导底层数据库引擎的查询图(Query Graph)。descend方法创建了该图的一个分支，该分支向下步入对象的结构中。每个descend方法就在这个树中构建一个结点，可以在这些结点上再附上一个约束(使用constrain方法)。用SQL的话来说，约束指定了查询的"WHERE"子句部分。多个约束可以在与(and)或或(or)方法的协助下结合起来。在上面的查询中我们已经使用了and方法去关联这些约束。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  <img src="http://www.blogjava.net/images/blogjava_net/jiangshachina/clip_image002.gif" alt="" border="0" /><br />
与其它的查询方式一样，查询结果返回到ObjectSet对象中，通过遍历该对象就可取出那些拿到的对象。<br />
&nbsp;&nbsp;&nbsp; 注意，由于S.O.D.A.是一种低层次的访问方法，没有智能的指示，它就没有默认的行为。访问cases对象的成员变量result字段的代码很简单<br />
&nbsp;&nbsp;&nbsp; query.descend("cases").descend("result"). ...<br />
我们并没有告诉S.O.D.A."cases"是一个集合对象。所以当查询执行时，它会不被察觉地检测ArrayList对象cases中所有元素(TestCase对象)的result字段，然后会正确地返回那些拥有符合搜索规范的测试用例的测试组。<br />
<br />
</span></span><span style="font-size: 10pt;"><strong><span style="font-size: 12pt;">db4o性能调优</span></strong><br />
&nbsp;&nbsp;&nbsp; 我们已经展示了db4o的基本操作(但无关紧要的删除操作除外，下面将会提到它)。但，正如我们在本文通篇所提到的，db4o发布(expose)了一个API层次结构，以允许开发者能够选择以何种层次的API去控制建立在该数据库引擎之上的应用程序。从另一方面看，如果你所想做的只是向数据库存入，及从数据库取出对象，那么你就已经看到了你所需要的一切。然而，如果你的应用的需求超出了添加，更新，查询和删除，可能还有一个db4o的特性可解决你的问题。<br />
&nbsp;&nbsp;&nbsp; db4o的ObjectContainer实际上发布(expose)了两个API。第一个API非常的简单，由十个方法组成。这些方法处理数据库的打开与关闭；添加，更新，查询和删除对象；及提交或中止事务。短言之，该API为你提供了在操纵数据库时所需要所有功能。然而，该API中的一个方法--ext()--是进入"被扩展的"ObjectContainer的一个入口。该被扩展的ObjectContainer为深入控制db4o的内部发布(expose)了更多方法。例如，你可以获得并改变数据库的配置上下文，使用它你能够修改该引擎的行为。<br />
&nbsp;&nbsp;&nbsp; 例如，假设你已经从数据库中拿到了一个TestSuite对象，发现该对象中的数据是错误的，并决定该对象应该被删除。此外，你还决定你必须删除的不仅是该TestSuite对象，而且还有所有与之关联的TestCase对象(在ArrayList对象cases中)。<br />
&nbsp;&nbsp;&nbsp; 你是可以冗长而乏味地遍历这个ArrayList对象，一个接一个地删除每一个TestCase对象，然后再删除TestSuite对象本身。可能一种更好的解决方案是为这个TestSuite对象启用db4o的"级联删除"特性。<br />
&nbsp;&nbsp;&nbsp; . . .<br />
&nbsp;&nbsp;&nbsp; // Fetch the database's configuration context<br />
&nbsp;&nbsp;&nbsp; Configuration config = db.ext().configure();<br />
&nbsp;&nbsp;&nbsp; // Get the ObjectClass for TestSuite<br />
&nbsp;&nbsp;&nbsp; ObjectClass oc = config.objectClass("testsuites.TestSuite");<br />
&nbsp;&nbsp;&nbsp; // Turn on cascaded delete<br />
&nbsp;&nbsp;&nbsp; oc.cascadeOnDelete(true);<br />
&nbsp;&nbsp;&nbsp; ...&nbsp; ...<br />
&nbsp;&nbsp;&nbsp; db.delete(ts1);<br />
&nbsp;&nbsp;&nbsp; . . .<br />
在上述代码中，我们实例化了一个ObjectClass对象，该对象使我们能够访问到TestSuite对象的db4o内部表现形式。我们打开cascadeOnDelete标记，以便当执行db4o.delete(ts1)时，不仅ts1对象会被删除，而且所有由ts1引用的TestCase对象也会被删除。(由于显而易见的原因，默认情况下，级联删除是被关闭的)<br />
&nbsp;&nbsp;&nbsp; 作为另一个例子，假设你想为数据库预分配存储空间，以至于要最小化磁盘驱动器的头移动(head movement)。(最好是在硬盘碎片整理之后，并新创建一个数据库时这样做。)并且假设以ObjectContainer对象db作为打开了的数据库：<br />
&nbsp;&nbsp;&nbsp; // Fetch the database's configuration context<br />
&nbsp;&nbsp;&nbsp; // 获得数据库的配置上下文<br />
&nbsp;&nbsp;&nbsp; Configuration config = db.ext().configure();<br />
&nbsp;&nbsp;&nbsp; // Pre-allocate 200,000 bytes<br />
&nbsp;&nbsp;&nbsp; // 预分配200000000字节<br />
&nbsp;&nbsp;&nbsp; config.reserveStorageSpace(200000000L);<br />
把数据库文件预扩展到200000000字节(略小于200兆字节)。假设该磁盘已经做碎片整理了，那么被分配的块就是连续的，这可显著提升数据库的访问。<br />
<br />
<strong><span style="font-size: 12pt;">db4o高级应用</span></strong><br />
&nbsp;&nbsp;&nbsp; 完全可以说，db4o在它不大的空间(约500K)内已装入了足够多的特性，相比较于db4o在运行过程中所做的众多事情，我们不能花费更多的笔墨去解释它们了。但是有两个特性十分突出，以至于肯定要提到它们。<br />
&nbsp;&nbsp;&nbsp; db4o的对象复制实现了被总称为面向对象版的数据库同步。使用复制所提供的功能，你能为一个数据库中的一个对象做一个副本，并将该副本放入另一个数据库中。使用这样的方法，副本对象就无形中和原始对象关联在了一起。对任一对象--原始对象或副本对象--的改变都会被跟踪到，以便在之后的某个时候，数据库能够被重组，并且这两个数据库中对象的不同之处可被分解(例如，可同步这两个数据库)。<br />
&nbsp;&nbsp;&nbsp; 它工作起来就像这样：为使一个数据库可被复制，与事务计数器一样，该数据库中被创建的任何一个对象都用一个唯一全局标识符(UUID)进行了标记。当你从原始数据库中"复制"一个对象到另一个数据库中，副本对象会带着与它的原始对象相同的UUID和事务计数器。副本数据库现在就可以从它的原始数据库那儿弄走了。修改副本对象的内容将会导致对象的事务计数器被修改。所以，当这两个数据库重新连接起来，db4o内建的同步处理机制就能一个对象一个对象地进行正确的匹配(使用UUID)，并确定原始或副本对象是否已经改变了。db4o甚至能追踪到每个对象发生最后一次修改时的时间，以便用户写的冲突解决代码能确定哪个对象是最近更新的。<br />
&nbsp;&nbsp;&nbsp; 从操作行为来看，db4o的同步处理机制与原生查询十分相似。回想一下，当实现了一个原生查询类时，我们要定义一个match方法，该方法确定哪些对象符合(或不符合)查询规范。使用同步复制，我们要定义一个ReplicationProcess对象，我们会把冲突处理对象传入该方法中。这些Java代码可能像这样：<br />
&nbsp;&nbsp;&nbsp; . . .<br />
&nbsp;&nbsp;&nbsp; ReplicationProcess replication = db1.ext().<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; replicationBegin(db2, new ReplicationConflictHandler()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Object resolveConflict(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ReplicationProcess rprocess, Object a, Object b)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; . . .&nbsp; ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return winning_object;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br />
在上述代码中，Object a是来自于数据库db1的对象，Object b则来自于数据库db2。默认情况下，同步是双向的。同步处理保证胜出的对象(由resolveConflict方法返回的对象)能存入这两个数据库中。所以当复制完成时，这两个数据库中被复制的对象就同步了。<br />
&nbsp;&nbsp;&nbsp; 最后，db4o最强大的特性之一就是它能毫不费力地容忍类结构的演变。假设，在向数据库内加入数百个TestSuite对象之后，我们决定这个类必须要被修改。就是说，我们已经被告之，该系统必须能追踪到每个TestSuite的执行QA工程师，所以必须加入如下字段<br />
&nbsp;&nbsp;&nbsp; private int engineerID;<br />
到TestSuite类的定义中。<br />
&nbsp;&nbsp;&nbsp; 现在我们就遇到了两个相关联的问题。第一个问题不是很糟糕：已存在于数据库中的用于表示测试的TestSuite对象，并没有为它们记录QA工程师的ID，所以我们将不得不将一个虚拟的值赋给这些对象的engineerID字段；该值会指出"未记录QA工程师的ID"。第二个问题就更难应付了：我们必须不知原因地把已有的TestSuite对象移植到"新的"类结构中。我们必须为数据库中所有已存在的TestSuite对象加上一个engineerID字段。除了把旧数据库中的对象复制到一个中间性的文件，然后重新创建一个数据库这种方法之外，我们还能怎么做呢？<br />
&nbsp;&nbsp;&nbsp; 幸运地是，使用db4o，我们确实什么都不用做。为了能操纵新的engineerID字段，以完成业务逻辑上所要求的变化，如果就只是向(我们的应用程序中的)TestSuite类添加一个engineerID字段，我们完全不必触动db4o API的任何调用。当db4o使用"新的"TestSuite类结构去读取"旧的"TestSuite对象，db4o将认为这些对象中的engineerID字段消失了，并且会优雅地把该字段的值设为0。如果我们把0当作"未记录QA工程师的ID"，那么我们所做的移植就完成了。写入到数据库中的新TestSuite对象将会包括新字段。(事实上，对旧的TestSuite对象本身进行重写，会使db4o不被察觉地为这些对象加上新字段。)所以，通过发布一个包含新的TestSuite定义的更新应用，我们完全可以不被察觉地从旧的TestSuite对象移植到新的...正如前述应用所做的那样。<br />
<br />
<strong><span style="font-size: 12pt;">全方位数据库</span></strong><br />
&nbsp;&nbsp;&nbsp; 通过适当地应用，db4o就能成为数据库中的"瑞士军刀"。它占用足够小的内存空间，使它能够被包含在一个不需要消耗大量资源的项目中。同样地，一个数据库只在磁盘上占用一个文件的事实可能会使人们在第一眼看到它时，不能认识到它丰富的功能。将数据库从一个地方移到另一个地方就是一个简单的文件拷贝；你不必担心分离的索引文件，数据文件，数据库结构文件等等这些文件的位置。对于快速部署和零管理的数据库应用，db4o很能胜任。<br />
&nbsp;&nbsp;&nbsp; 另外，根据我们已多次描述过的，db4o在简单性和优雅之间达到了适度的平衡。db4o的QBE既如此的简单，又如此的功能强大，对于一组令人惊奇的应用，它经常是我们唯一需要的查询API。如果你主要是通过指针导航而不是查询去访问数据库，QBE就特别有吸引力。在这种情况下，QBE经常能高效地拿到一个对象网络(Object Network)的根对象。然后，你就能使用db4o的激活(activation)功能从根部向下进行对象引用导航，如果这些对象都完全在内存中的话，你就更可以这么做了。<br />
&nbsp;&nbsp;&nbsp; 而在使用QBE并不高效的时候，原生查询和S.O.D.A.就能派上用场了，并且它们伴随着一堆特性和低层次的API。我们还没有展示db4o的加密功能，插入式文件I/O(例如，它允许你添加"写后读(read-after-write)"验证)，信号量，客户端/服务器端模式，以及其它难以计数的功能。我们结论性的建议很简单：当你的下一个Java应用需要一个数据库，在最终开始编码之前，你可以去访问一下http://www.db4objects.com/。这是很值得的。<br />
</span><br />
<img src ="http://www.blogjava.net/jiangshachina/aggbug/164430.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangshachina/" target="_blank">Sha Jiang</a> 2007-12-05 12:31 <a href="http://www.blogjava.net/jiangshachina/archive/2007/12/05/164430.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySQL索引(摘)</title><link>http://www.blogjava.net/jiangshachina/archive/2007/07/03/127728.html</link><dc:creator>Sha Jiang</dc:creator><author>Sha Jiang</author><pubDate>Tue, 03 Jul 2007 00:44:00 GMT</pubDate><guid>http://www.blogjava.net/jiangshachina/archive/2007/07/03/127728.html</guid><wfw:comment>http://www.blogjava.net/jiangshachina/comments/127728.html</wfw:comment><comments>http://www.blogjava.net/jiangshachina/archive/2007/07/03/127728.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangshachina/comments/commentRss/127728.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangshachina/services/trackbacks/127728.html</trackback:ping><description><![CDATA[<div style="text-align: center;"><span style="font-size: 12pt; font-weight: bold;"><span style="font-size: 14pt;">MySQL索引</span></span><br />
</div>
<span style="font-size: 10pt;">&nbsp;&nbsp;&nbsp; 本文介绍了数据库索引，及其优、缺点。针对MySQL索引的特点、应用进行了详细的描述。分析了如何避免MySQL无法使用，如何使用EXPLAIN分析查询语句，如何优化MySQL索引的应用。本文摘自《MySQL 5权威指南》(3rd)的8.9节。(2007.07.05最后更新)<br />
<br />
&nbsp;&nbsp;&nbsp; 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分)，它们包含着对数据表里所有记录的引用指针。<br />
&nbsp;&nbsp;&nbsp; 注：[1]索引不是万能的！索引可以加快数据检索操作，但会使数据修改操作变慢。每修改数据记录，索引就必须刷新一次。为了在某种程序上弥补这一缺陷，许多SQL命令都有一个DELAY_KEY_WRITE项。这个选项的作用是暂时制止MySQL在该命令每插入一条新记录和每修改一条现有之后立刻对索引进行刷新，对索引的刷新将等到全部记录插入/修改完毕之后再进行。在需要把许多新记录插入某个数据表的场合，DELAY_KEY_WRITE选项的作用将非常明显。[2]另外，索引还会在硬盘上占用相当大的空间。因此应该只为最经常查询和最经常排序的数据列建立索引。注意，如果某个数据列包含许多重复的内容，为它建立索引就没有太大的实际效果。<br />
&nbsp;&nbsp;&nbsp; 从理论上讲，完全可以为数据表里的每个字段分别建一个索引，但MySQL把同一个数据表里的索引总数限制为16个。<br />
&nbsp;&nbsp;&nbsp; 1. InnoDB数据表的索引<br />
&nbsp;&nbsp;&nbsp; 与MyISAM数据表相比，索引对InnoDB数据的重要性要大得多。在InnoDB数据表上，索引对InnoDB数据表的重要性要在得多。在InnoDB数据表上，索引不仅会在搜索数据记录时发挥作用，还是数据行级锁定机制的苊、基础。"数据行级锁定"的意思是指在事务操作的执行过程中锁定正在被处理的个别记录，不让其他用户进行访问。这种锁定将影响到(但不限于)SELECT...LOCK IN SHARE MODE、SELECT...FOR UPDATE命令以及INSERT、UPDATE和DELETE命令。<br />
&nbsp;&nbsp;&nbsp; 出于效率方面的考虑，InnoDB数据表的数据行级锁定实际发生在它们的索引上，而不是数据表自身上。显然，数据行级锁定机制只有在有关的数据表有一个合适的索引可供锁定的时候才能发挥效力。<br />
&nbsp;&nbsp;&nbsp; 2. 限制<br />
&nbsp;&nbsp;&nbsp; 如果WEHERE子句的查询条件里有不等号(WHERE coloum != ...)，MySQL将无法使用索引。<br />
&nbsp;&nbsp;&nbsp; 类似地，如果WHERE子句的查询条件里使用了函数(WHERE DAY(column) = ...)，MySQL也将无法使用索引。<br />
&nbsp;&nbsp;&nbsp; 在JOIN操作中(需要从多个数据表提取数据时)，MySQL只有在主键和外键的数据类型相同时才能使用索引。<br />
&nbsp;&nbsp;&nbsp; 如果WHERE子句的查询条件里使用比较操作符LIKE和REGEXP，MySQL只有在搜索模板的第一个字符不是通配符的情况下才能使用索引。比如说，如果查询条件是LIKE 'abc%'，MySQL将使用索引；如果查询条件是LIKE '%abc'，MySQL将不使用索引。<br />
&nbsp;&nbsp;&nbsp; 在ORDER BY操作中，MySQL只有在排序条件不是一个查询条件表达式的情况下才使用索引。(虽然如此，在涉及多个数据表查询里，即使有索引可用，那些索引在加快ORDER BY方面也没什么作用)<br />
&nbsp;&nbsp;&nbsp; 如果某个数据列里包含许多重复的值，就算为它建立了索引也不会有很好的效果。比如说，如果某个数据列里包含的净是些诸如"0/1"或"Y/N"等值，就没有必要为它创建一个索引。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 普通索引、唯一索引和主索引<br />
&nbsp;&nbsp;&nbsp; 1. 普通索引<br />
&nbsp;&nbsp;&nbsp; 普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。因此，应该只为那些最经常出现在查询条件(WHERE column = ...)或排序条件(ORDER BY column)中的数据列创建索引。只要有可能，就应该选择一个数据最整齐、最紧凑的数据列(如一个整数类型的数据列)来创建索引。<br />
&nbsp;&nbsp;&nbsp; 2. 唯一索引<br />
&nbsp;&nbsp;&nbsp; 普通索引允许被索引的数据列包含重复的值。比如说，因为人有可能同名，所以同一个姓名在同一个"员工个人资料"数据表里可能出现两次或更多次。<br />
&nbsp;&nbsp;&nbsp; 如果能确定某个数据列将只包含彼此各不相同的值，在为这个数据列创建索引的时候就应该用关键字UNIQUE把它定义为一个唯一索引。这么做的好处：一是简化了MySQL对这个索引的管理工作，这个索引也因此而变得更有效率；二是MySQL会在有新记录插入数据表时，自动检查新记录的这个字段的值是否已经在某个记录的这个字段里出现过了；如果是，MySQL将拒绝插入那条新记录。也就是说，唯一索引可以保证数据记录的唯一性。事实上，在许多场合，人们创建唯一索引的目的往往不是为了提高访问速度，而只是为了避免数据出现重复。<br />
&nbsp;&nbsp;&nbsp; 3. 主索引<br />
&nbsp;&nbsp;&nbsp; 在前面已经反复多次强调过：必须为主键字段创建一个索引，这个索引就是所谓的"主索引"。主索引与唯一索引的唯一区别是：前者在定义时使用的关键字是PRIMARY而不是UNIQUE。<br />
&nbsp;&nbsp;&nbsp; 4. 外键索引<br />
&nbsp;&nbsp;&nbsp; 如果为某个外键字段定义了一个外键约束条件，MySQL就会定义一个内部索引来帮助自己以最有效率的方式去管理和使用外键约束条件。<br />
&nbsp;&nbsp;&nbsp; 5. 复合索引<br />
&nbsp;&nbsp;&nbsp; 索引可以覆盖多个数据列，如像INDEX(columnA, columnB)索引。这种索引的特点是MySQL可以有选择地使用一个这样的索引。如果查询操作只需要用到columnA数据列上的一个索引，就可以使用复合索引INDEX(columnA, columnB)。不过，这种用法仅适用于在复合索引中排列在前的数据列组合。比如说，INDEX(A, B, C)可以当做A或(A, B)的索引来使用，但不能当做B、C或(B, C)的索引来使用。<br />
&nbsp;&nbsp;&nbsp; 6. 索引的长度<br />
&nbsp;&nbsp;&nbsp; 在为CHAR和VARCHAR类型的数据列定义索引时，可以把索引的长度限制为一个给定的字符个数(这个数字必须小于这个字段所允许的最大字符个数)。这么做的好处是可以生成一个尺寸比较小、检索速度却比较快的索引文件。在绝大多数应用里，数据库中的字符串数据大都以各种各样的名字为主，把索引的长度设置为10~15个字符已经足以把搜索范围缩小到很少的几条数据记录了。<br />
&nbsp;&nbsp;&nbsp; 在为BLOB和TEXT类型的数据列创建索引时，必须对索引的长度做出限制；MySQL所允许的最大索引长度是255个字符。<br />
<br />
&nbsp;&nbsp;&nbsp; 全文索引<br />
&nbsp;&nbsp;&nbsp; 文本字段上的普通索引只能加快对出现在字段内容最前面的字符串(也就是字段内容开头的字符)进行检索操作。如果字段里存放的是由几个、甚至是多个单词构成的较大段文字，普通索引就没什么作用了。这种检索往往以LIKE %word%的形式出现，这对MySQL来说很复杂，如果需要处理的数据量很大，响应时间就会很长。<br />
&nbsp;&nbsp;&nbsp; 这类场合正是全文索引(full-text index)可以大显身手的地方。在生成这种类型的索引时，MySQL将把在文本中出现的所有单词创建为一份清单，查询操作将根据这份清单去检索有关的数据记录。全文索引即可以随数据表一同创建，也可以等日后有必要时再使用下面这条命令添加：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ALTER TABLE tablename ADD FULLTEXT(column1, column2)<br />
&nbsp;&nbsp;&nbsp; 有了全文索引，就可以用SELECT查询命令去检索那些包含着一个或多个给定单词的数据记录了。下面是这类查询命令的基本语法：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SELECT * FROM tablename<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHERE MATCH(column1, column2) AGAINST('word1', 'word2', 'word3')<br />
&nbsp;&nbsp;&nbsp; 上面这条命令将把column1和column2字段里有word1、word2和word3的数据记录全部查询出来。<br />
&nbsp;&nbsp;&nbsp; 注解：InnoDB数据表不支持全文索引。<br />
<br />
&nbsp;&nbsp;&nbsp; 查询和索引的优化<br />
&nbsp;&nbsp;&nbsp; 只有当数据库里已经有了足够多的测试数据时，它的性能测试结果才有实际参考价值。如果在测试数据库里只有几百条数据记录，它们往往在执行完第一条查询命令之后就被全部加载到内存里，这将使后续的查询命令都执行得非常快--不管有没有使用索引。只有当数据库里的记录超过了1000条、数据总量也超过了MySQL服务器上的内存总量时，数据库的性能测试结果才有意义。<br />
&nbsp;&nbsp;&nbsp; 在不确定应该在哪些数据列上创建索引的时候，人们从EXPLAIN SELECT命令那里往往可以获得一些帮助。这其实只是简单地给一条普通的SELECT命令加一个EXPLAIN关键字作为前缀而已。有了这个关键字，MySQL将不是去执行那条SELECT命令，而是去对它进行分析。MySQL将以表格的形式把查询的执行过程和用到的索引(如果有的话)等信息列出来。<br />
&nbsp;&nbsp;&nbsp; 在EXPLAIN命令的输出结果里，第1列是从数据库读取的数据表的名字，它们按被读取的先后顺序排列。type列指定了本数据表与其它数据表之间的关联关系(JOIN)。在各种类型的关联关系当中，效率最高的是system，然后依次是const、eq_ref、ref、range、index和All(All的意思是：对应于上一级数据表里的每一条记录，这个数据表里的所有记录都必须被读取一遍--这种情况往往可以用一索引来避免)。<br />
&nbsp;&nbsp;&nbsp; possible_keys数据列给出了MySQL在搜索数据记录时可选用的各个索引。key数据列是MySQL实际选用的索引，这个索引按字节计算的长度在key_len数据列里给出。比如说，对于一个INTEGER数据列的索引，这个字节长度将是4。如果用到了复合索引，在key_len数据列里还可以看到MySQL具体使用了它的哪些部分。作为一般规律，key_len数据列里的值越小越好(意思是更快)。<br />
&nbsp;&nbsp;&nbsp; ref数据列给出了关联关系中另一个数据表里的数据列的名字。row数据列是MySQL在执行这个查询时预计会从这个数据表里读出的数据行的个数。row数据列里的所有数字的乘积可以让我们大致了解这个查询需要处理多少组合。<br />
&nbsp;&nbsp;&nbsp; 最后，extra数据列提供了与JOIN操作有关的更多信息，比如说，如果MySQL在执行这个查询时必须创建一个临时数据表，就会在extra列看到using temporary字样。<br />
<br />
</span>       
<img src ="http://www.blogjava.net/jiangshachina/aggbug/127728.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangshachina/" target="_blank">Sha Jiang</a> 2007-07-03 08:44 <a href="http://www.blogjava.net/jiangshachina/archive/2007/07/03/127728.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>My.cnf配置选项(摘)</title><link>http://www.blogjava.net/jiangshachina/archive/2007/05/23/119308.html</link><dc:creator>Sha Jiang</dc:creator><author>Sha Jiang</author><pubDate>Wed, 23 May 2007 01:26:00 GMT</pubDate><guid>http://www.blogjava.net/jiangshachina/archive/2007/05/23/119308.html</guid><wfw:comment>http://www.blogjava.net/jiangshachina/comments/119308.html</wfw:comment><comments>http://www.blogjava.net/jiangshachina/archive/2007/05/23/119308.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangshachina/comments/commentRss/119308.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangshachina/services/trackbacks/119308.html</trackback:ping><description><![CDATA[<div style="text-align: center;"><span style="font-size: 12pt; font-weight: bold;"><span style="font-size: 14pt;"><span style="font-size: 14pt;">My.cnf配置选项</span></span></span><br />
</div>
<span style="font-size: 10pt;">本文中的配置都是从《MySQL5权威指南(3rd)》中摘抄出来的，个人认为对于使用MySQL十分有用。放在此处方便自己随时查阅，也希望对其他朋友有所助益。(2007.05.30最后更新)<br />
<br />
mysqld程序--目录和文件<br />
basedir = path&nbsp; 使用给定目录作为根目录(安装目录)。<br />
character-sets-dir = path&nbsp; 给出存放着字符集的目录。<br />
datadir = path&nbsp; 从给定目录读取数据库文件。<br />
pid-file = filename&nbsp; 为mysqld程序指定一个存放进程ID的文件(仅适用于UNIX/Linux系统); Init-V脚本需要使用这个文件里的进程ID结束mysqld进程。<br />
socket = filename&nbsp; 为MySQL客户程序与服务器之间的本地通信指定一个套接字文件(仅适用于UNIX/Linux系统; 默认设置一般是/var/lib/mysql/mysql.sock文件)。<br />
&nbsp;&nbsp;&nbsp; 在Windows环境下，如果MySQL客户与服务器是通过命名管道进行通信的，--sock选项给出的将是该命名管道的名字(默认设置是MySQL)。<br />
lower_case_table_name = 1/0&nbsp; 新目录和数据表的名字是否只允许使用小写字母; 这个选项在Windows环境下的默认设置是1(只允许使用小写字母)。<br />
<br />
mysqld程序--语言设置<br />
character-sets-server = name&nbsp; 新数据库或数据表的默认字符集。为了与MySQL的早期版本保持兼容，这个字符集也可以用--default-character-set选项给出; 但这个选项已经显得有点过时了。<br />
collation-server = name&nbsp; 新数据库或数据表的默认排序方式。<br />
lanuage = name&nbsp; 用指定的语言显示出错信息。<br />
<br />
mysqld程序--通信、网络、信息安全<br />
enable-named-pipes&nbsp; 允许Windows 2000/XP环境下的客户和服务器使用命名管道(named pipe)进行通信。这个命名管道的默认名字是MySQL，但可以用--socket选项来改变。<br />
local-infile [=0]&nbsp; 允许/禁止使用LOAD DATA LOCAL语句来处理本地文件。<br />
myisam-recover [=opt1, opt2, ...]&nbsp; 在启动时自动修复所有受损的MyISAM数据表。这个选项的可取值有4种:DEFAULT、BACKUP、QUICK和FORCE; 它们与myisamchk程序的同名选项作用相同。<br />
old-passwords&nbsp; 使用MySQL 3.23和4.0版本中的老算法来加密mysql数据库里的密码(默认使用MySQL 4.1版本开始引入的新加密算法)。<br />
port = n&nbsp; 为MySQL程序指定一个TCP/IP通信端口(通常是3306端口)。<br />
safe-user-create&nbsp; 只有在mysql.user数据库表上拥有INSERT权限的用户才能使用GRANT命令; 这是一种双保险机制(此用户还必须具备GRANT权限才能执行GRANT命令)。<br />
shared-memory&nbsp; 允许使用内存(shared memory)进行通信(仅适用于Windows)。<br />
shared-memory-base-name = name&nbsp; 给共享内存块起一个名字(默认的名字是MySQL)。<br />
skip-grant-tables&nbsp; 不使用mysql数据库里的信息来进行访问控制(警告:这将允许用户任何用户去修改任何数据库)。<br />
skip-host-cache&nbsp; 不使用高速缓存区来存放主机名和IP地址的对应关系。<br />
skip-name-resovle&nbsp; 不把IP地址解析为主机名; 与访问控制(mysql.user数据表)有关的检查全部通过IP地址行进。<br />
skip-networking&nbsp;
只允许通过一个套接字文件(Unix/Linux系统)或通过命名管道(Windows系统)进行本地连接，不允许ICP/IP连接;
这提高了安全性，但阻断了来自网络的外部连接和所有的Java客户程序(Java客户即使在本地连接里也使用TCP/IP)。<br />
user = name&nbsp; mysqld程序在启动后将在给定UNIX/Linux账户下执行; mysqld必须从root账户启动才能在启动后切换到另一个账户下执行; mysqld_safe脚本将默认使用--user=mysql选项来启动mysqld程序。<br />
<br />
mysqld程序--内存管理、优化、查询缓存区<br />
bulk_insert_buffer_size = n&nbsp; 为一次插入多条新记录的INSERT命令分配的缓存区长度(默认设置是8M)。<br />
key_buffer_size = n&nbsp; 用来存放索引区块的RMA值(默认设置是8M)。<br />
join_buffer_size = n&nbsp; 在参加JOIN操作的数据列没有索引时为JOIN操作分配的缓存区长度(默认设置是128K)。<br />
max_heap_table_size = n&nbsp; HEAP数据表的最大长度(默认设置是16M); 超过这个长度的HEAP数据表将被存入一个临时文件而不是驻留在内存里。<br />
max_connections = n&nbsp; MySQL服务器同时处理的数据库连接的最大数量(默认设置是100)。<br />
query_cache_limit = n&nbsp; 允许临时存放在查询缓存区里的查询结果的最大长度(默认设置是1M)。<br />
query_cache_size = n&nbsp; 查询缓存区的最大长度(默认设置是0，不开辟查询缓存区)。<br />
query_cache_type = 0/1/2&nbsp; 查询缓存区的工作模式:0, 禁用查询缓存区; 1，启用查询缓存区(默认设置); 2，"按需分配"模式，只响应SELECT SQL_CACHE命令。<br />
read_buffer_size = n&nbsp; 为从数据表顺序读取数据的读操作保留的缓存区的长度(默认设置是128KB); 这个选项的设置值在必要时可以用SQL命令SET SESSION read_buffer_size = n命令加以改变。<br />
read_rnd_buffer_size = n&nbsp; 类似于read_buffer_size选项，但针对的是按某种特定顺序(比如使用了ORDER BY子句的查询)输出的查询结果(默认设置是256K)。<br />
sore_buffer = n&nbsp; 为排序操作分配的缓存区的长度(默认设置是2M); 如果这个缓存区太小，则必须创建一个临时文件来进行排序。<br />
table_cache = n&nbsp; 同时打开的数据表的数量(默认设置是64)。<br />
tmp_table_size = n&nbsp; 临时HEAP数据表的最大长度(默认设置是32M); 超过这个长度的临时数据表将被转换为MyISAM数据表并存入一个临时文件。<br />
<br />
mysqld程序--日志<br />
log [= file]&nbsp; 把所有的连接以及所有的SQL命令记入日志(通用查询日志); 如果没有给出file参数，MySQL将在数据库目录里创建一个hostname.log文件作为这种日志文件(hostname是服务器的主机名)。<br />
log-slow-queries
[= file]&nbsp; 把执行用时超过long_query_time变量值的查询命令记入日志(慢查询日志);
如果没有给出file参数，MySQL将在数据库目录里创建一个hostname-slow.log文件作为这种日志文件(hostname是服务器主机
名)。<br />
long_query_time = n&nbsp; 慢查询的执行用时上限(默认设置是10s)。<br />
long_queries_not_using_indexs&nbsp; 把慢查询以及执行时没有使用索引的查询命令全都记入日志(其余同--log-slow-queries选项)。<br />
log-bin
[= filename]&nbsp;
把对数据进行修改的所有SQL命令(也就是INSERT、UPDATE和DELETE命令)以二进制格式记入日志(二进制变更日志，binary
update log)。这种日志的文件名是filename.n或默认的hostname.n，其中n是一个6位数字的整数(日志文件按顺序编号)。<br />
log-bin-index = filename&nbsp; 二进制日志功能的索引文件名。在默认情况下，这个索引文件与二进制日志文件的名字相同，但后缀名是.index而不是.nnnnnn。<br />
max_binlog_size = n&nbsp; 二进制日志文件的最大长度(默认设置是1GB)。在前一个二进制日志文件里的信息量超过这个最大长度之前，MySQL服务器会自动提供一个新的二进制日志文件接续上。<br />
binlog-do-db = dbname&nbsp; 只把给定数据库里的变化情况记入二进制日志文件，其他数据库里的变化情况不记载。如果需要记载多个数据库里的变化情况，就必须在配置文件使用多个本选项来设置，每个数据库一行。<br />
binlog-ignore-db = dbname&nbsp; 不把给定数据库里的变化情况记入二进制日志文件。<br />
sync_binlog = n&nbsp; 每经过n次日志写操作就把日志文件写入硬盘一次(对日志信息进行一次同步)。n=1是最安全的做法，但效率最低。默认设置是n=0，意思是由操作系统来负责二进制日志文件的同步工作。<br />
log-update [= file]&nbsp; 记载出错情况的日志文件名(出错日志)。这种日志功能无法禁用。如果没有给出file参数，MySQL会使用hostname.err作为种日志文件的名字。<br />
<br />
mysqld程序--镜像(主控镜像服务器)<br />
server-id = n&nbsp; 给服务器分配一个独一无二的ID编号; n的取值范围是1~2的32次方启用二进制日志功能。<br />
log-bin = name&nbsp; 启用二进制日志功能。这种日志的文件名是filename.n或默认的hostname.n，其中的n是一个6位数字的整数(日志文件顺序编号)。<br />
binlog-do/ignore-db = dbname&nbsp; 只把给定数据库里的变化情况记入二进制日志文件/不把给定的数据库里的变化记入二进制日志文件。<br />
<br />
mysqld程序--镜像(从属镜像服务器)<br />
server-id = n&nbsp; 给服务器分配一个唯一的ID编号<br />
log-slave-updates&nbsp; 启用从属服务器上的日志功能，使这台计算机可以用来构成一个镜像链(A-&gt;B-&gt;C)。<br />
master-host = hostname&nbsp; 主控服务器的主机名或IP地址。如果从属服务器上存在mater.info文件(镜像关系定义文件)，它将忽略此选项。<br />
master-user = replicusername&nbsp; 从属服务器用来连接主控服务器的用户名。如果从属服务器上存在mater.info文件，它将忽略此选项。<br />
master-password = passwd&nbsp; 从属服务器用来连接主控服务器的密码。如果从属服务器上存在mater.info文件，它将忽略此选项。<br />
master-port = n&nbsp; 从属服务器用来连接主控服务器的TCP/IP端口(默认设置是3306端口)。<br />
master-connect-retry = n&nbsp; 如果与主控服务器的连接没有成功，则等待n秒(s)后再进行管理方式(默认设置是60s)。如果从属服务器存在mater.info文件，<br />
&nbsp;&nbsp;&nbsp; 它将忽略此选项。<br />
master-ssl-xxx = xxx&nbsp; 对主、从服务器之间的SSL通信进行配置。<br />
read-only = 0/1&nbsp; 0: 允许从属服务器独立地执行SQL命令(默认设置); 1: 从属服务器只能执行来自主控服务器的SQL命令。<br />
read-log-purge = 0/1&nbsp; 1: 把处理完的SQL命令立刻从中继日志文件里删除(默认设置); 0: 不把处理完的SQL命令立刻从中继日志文件里删除。<br />
replicate-do-table = dbname.tablename&nbsp; 与--replicate-do-table选项的含义和用法相同，但数据库和数据库表名字里允许出现通配符"%"<br />
&nbsp;&nbsp;&nbsp; (例如: test%.%--对名字以"test"开头的所有数据库里的所以数据库表进行镜像处理)。<br />
replicate-do-db = name&nbsp; 只对这个数据库进行镜像处理。<br />
replicate-ignore-table = dbname.tablename&nbsp; 不对这个数据表进行镜像处理。<br />
replicate-wild-ignore-table = dbn.tablen&nbsp; 不对这些数据表进行镜像处理。<br />
replicate-ignore-db = dbname&nbsp; 不对这个数据库进行镜像处理。<br />
replicate-rewrite-db = db1name &gt; db2name&nbsp; 把主控数据库上的db1name数据库镜像处理为从属服务器上的db2name数据库。<br />
report-host = hostname&nbsp; 从属服务器的主机名; 这项信息只与SHOW SLAVE HOSTS命令有关--主控服务器可以用这条命令生成一份从属服务器的名单。<br />
slave-compressed-protocol = 1&nbsp; 主、从服务器使用压缩格式进行通信--如果它们都支持这么做的话。<br />
slave-skip-errors = n1, n2, ...或all&nbsp; 即使发生出错代码为n1、n2等的错误，镜像处理工作也继续进行(即不管发生什么错误，镜像处理工作也继续进行)。<br />
&nbsp;&nbsp;&nbsp; 如果配置得当，从属服务器不应该在执行SQL命令时发生错误(在主控服务器上执行出错的SQL命令不会被发送到从属服务器上做镜像处理); 如果不使用<br />
&nbsp;&nbsp;&nbsp; slave-skip-errors选项，从属服务器上的镜像工作就可能国为发生错误而中断，中断后需要有人工参与才能继续进行。<br />
<br />
mysqld--InnoDB--基本设置、表空间文件<br />
skip-innodb&nbsp; 不加载InnoDB数据表驱动程序--如果用不着InnoDB数据表，可以用这个选项节省一些内存。<br />
innodb-file-per-table&nbsp; 为每一个新数据表创建一个表空间文件而不是把数据表都集中保存在中央表空间里(后者是默认设置)。该选项始见于MySQL 4.1。<br />
innodb-open-file = n&nbsp; InnoDB数据表驱动程序最多可以同时打开的文件数(默认设置是300)。如果使用了innodb-file-per-table选项并且需要同时打开很多<br />
&nbsp;&nbsp;&nbsp; 数据表的话，这个数字很可能需要加大。<br />
innodb_data_home_dir = p&nbsp; InnoDB主目录，所有与InnoDB数据表有关的目录或文件路径都相对于这个路径。在默认的情况下，这个主目录就是MySQL的数据目录。<br />
innodb_data_file_path = ts&nbsp; 用来容纳InnoDB为数据表的表空间: 可能涉及一个以上的文件; 每一个表空间文件的最大长度都必须以字节(B)、兆字节(MB)或<br />
&nbsp;&nbsp;&nbsp; 千兆字节(GB)为单位给出; 表空间文件的名字必须以分号隔开; 最后一个表空间文件还可以带一个autoextend属性和一个最大长度(max:n)。<br />
&nbsp;&nbsp;&nbsp; 例如，ibdata1:1G; ibdata2:1G:autoextend:max:2G的意思是: 表空间文件ibdata1的最大长度是1GB，ibdata2的最大长度也是1G，但允许它扩充到2GB。<br />
&nbsp;&nbsp;&nbsp; 除文件名外，还可以用硬盘分区的设置名来定义表空间，此时必须给表空间的最大初始长度值加上newraw关键字做后缀，给表空间的最大扩充长度值加上<br />
&nbsp;&nbsp;&nbsp; raw关键字做后缀(例如/dev/hdb1:20Gnewraw或/dev/hdb1:20Graw); MySQL 4.0及更高版本的默认设置是ibdata1:10M:autoextend。<br />
innodb_autoextend_increment = n&nbsp; 带有autoextend属性的表空间文件每次加大多少兆字节(默认设置是8MB)。这个属性不涉及具体的数据表文件，那些文件的<br />
&nbsp;&nbsp;&nbsp; 增大速度相对是比较小的。<br />
innodb_lock_wait_timeout = n&nbsp; 如果某个事务在等待n秒(s)后还没有获得所需要的资源，就使用ROLLBACK命令放弃这个事务。这项设置对于发现和处理未能被<br />
&nbsp;&nbsp;&nbsp; InnoDB数据表驱动程序识别出来的死锁条件有着重要的意义。这个选项的默认设置是50s。<br />
innodb_fast_shutdown 0/1&nbsp; 是否以最快的速度关闭InnoDB，默认设置是1，意思是不把缓存在INSERT缓存区的数据写入数据表，那些数据将在MySQL服务器下次<br />
&nbsp;&nbsp;&nbsp; 启动时再写入(这么做没有什么风险，因为INSERT缓存区是表空间的一个组成部分，数据不会丢失)。把这个选项设置为0反面危险，因为在计算机关闭时，<br />
&nbsp;&nbsp;&nbsp; InnoDB驱动程序很可能没有足够的时间完成它的数据同步工作，操作系统也许会在它完成数据同步工作之前强行结束InnoDB，而这会导致数据不完整。<br />
<br />
mysqld程序--InnoDB--日志<br />
innodb_log_group_home_dir = p&nbsp; 用来存放InnoDB日志文件的目录路径(如ib_logfile0、ib_logfile1等)。在默认的情况下，InnoDB驱动程序将使用MySQL数据目<br />
&nbsp;&nbsp;&nbsp; 录作为自己保存日志文件的位置。&nbsp;&nbsp;&nbsp; <br />
innodb_log_files_in_group = n&nbsp; 使用多少个日志文件(默认设置是2)。InnoDB数据表驱动程序将以轮转方式依次填写这些文件; 当所有的日志文件都写满以后，<br />
&nbsp;&nbsp;&nbsp; 之后的日志信息将写入第一个日志文件的最大长度(默认设置是5MB)。这个长度必须以MB(兆字节)或GB(千兆字节)为单位进行设置。<br />
innodb_flush_log_at_trx_commit = 0/1/2&nbsp; 这个选项决定着什么时候把日志信息写入日志文件以及什么时候把这些文件物理地写(术语称为"同步")到硬盘上。<br />
&nbsp;&nbsp;&nbsp; 设置值0的意思是每隔一秒写一次日志并进行同步，这可以减少硬盘写操作次数，但可能造成数据丢失; 设置值1(设置设置)的意思是在每执行完一条COMMIT<br />
&nbsp;&nbsp;&nbsp; 命令就写一次日志并进行同步，这可以防止数据丢失，但硬盘写操作可能会很频繁; 设置值2是一般折衷的办法，即每执行完一条COMMIT命令写一次日志，<br />
&nbsp;&nbsp;&nbsp; 每隔一秒进行一次同步。<br />
innodb_flush_method = x&nbsp; InnoDB日志文件的同步办法(仅适用于UNIX/Linux系统)。这个选项的可取值有两种: fdatasync，用fsync()函数进行同步; O_DSYNC，<br />
&nbsp;&nbsp;&nbsp; 用O_SYNC()函数进行同步。<br />
innodb_log_archive = 1&nbsp; 启用InnoDB驱动程序的archive(档案)日志功能，把日志信息写入ib_arch_log_n文件。启用这种日志功能在InnoDB与MySQL一起使用时没有<br />
&nbsp;&nbsp;&nbsp; 多大意义(启用MySQL服务器的二进制日志功能就足够用了)。<br />
<br />
mysqld程序--InnoDB--缓存区的设置和优化<br />
innodb_log_buffer_pool_size = n&nbsp; 为InnoDB数据表及其索引而保留的RAM内存量(默认设置是8MB)。这个参数对速度有着相当大的影响，如果计算机上只运行有<br />
&nbsp;&nbsp;&nbsp; MySQL/InnoDB数据库服务器，就应该把全部内存的80%用于这个用途。<br />
innodb_log_buffer_size = n&nbsp; 事务日志文件写操作缓存区的最大长度(默认设置是1MB)。<br />
innodb_additional_men_pool_size = n&nbsp; 为用于内部管理的各种数据结构分配的缓存区最大长度(默认设置是1MB)。<br />
innodb_file_io_threads = n&nbsp; I/O操作(硬盘写操作)的最大线程个数(默认设置是4)。<br />
innodb_thread_concurrency = n&nbsp; InnoDB驱动程序能够同时使用的最大线程个数(默认设置是8)。<br />
<br />
mysqld程序--其它选项<br />
bind-address = ipaddr&nbsp; MySQL服务器的IP地址。如果MySQL服务器所在的计算机有多个IP地址，这个选项将非常重要。<br />
default-storage-engine = type&nbsp; 新数据表的默认数据表类型(默认设置是MyISAM)。这项设置还可以通过--default-table-type选项来设置。<br />
default-timezone = name&nbsp; 为MySQL服务器设置一个地理时区(如果它与本地计算机的地理时区不一样)。<br />
ft_min_word_len = n&nbsp; 全文索引的最小单词长度工。这个选项的默认设置是4，意思是在创建全文索引时不考虑那些由3个或更少的字符构建单词。<br />
Max-allowed-packet = n&nbsp; 客户与服务器之间交换的数据包的最大长度，这个数字至少应该大于客户程序将要处理的最大BLOB块的长度。这个选项的默认设置是1MB。<br />
Sql-mode = model1, mode2, ...&nbsp; MySQL将运行在哪一种SQL模式下。这个选项的作用是让MySQL与其他的数据库系统保持最大程度的兼容。这个选项的可取值包括<br />
&nbsp;&nbsp;&nbsp; ansi、db2、oracle、no_zero_date、pipes_as_concat。<br />
<br />
注意：如果在配置文件里给出的某个选项是mysqld无法识别的(如，因为犯了一个愚蠢的打字错误)，MySQL服务器将不启动。<br />
<br />
</span>
<img src ="http://www.blogjava.net/jiangshachina/aggbug/119308.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangshachina/" target="_blank">Sha Jiang</a> 2007-05-23 09:26 <a href="http://www.blogjava.net/jiangshachina/archive/2007/05/23/119308.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Apache2+MySQL5+PHP5安装(原)</title><link>http://www.blogjava.net/jiangshachina/archive/2007/01/02/91369.html</link><dc:creator>Sha Jiang</dc:creator><author>Sha Jiang</author><pubDate>Tue, 02 Jan 2007 05:48:00 GMT</pubDate><guid>http://www.blogjava.net/jiangshachina/archive/2007/01/02/91369.html</guid><wfw:comment>http://www.blogjava.net/jiangshachina/comments/91369.html</wfw:comment><comments>http://www.blogjava.net/jiangshachina/archive/2007/01/02/91369.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangshachina/comments/commentRss/91369.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangshachina/services/trackbacks/91369.html</trackback:ping><description><![CDATA[<div align="center">
<strong><span style="font-size: 14pt;"><strong>在Linux上安装Apache2+MySQL5+PHP5</strong>
</span></strong><br />
</div>
<font size="2">最近由于工作原因，在RedHat AS 4.0上安装了Apache2+MySQL5+PHP5。现将安装使用的命令记录，以备日后查询，也希望对其他朋友有帮助。(2007.10.17最后更新)<br />
&nbsp;&nbsp;&nbsp; 使用Apache2.0.59，MySQL5.0.16和PHP5.1.4的源代码包进行安装。假设这三源代码安装包已经解压，且路径分别为:<font color="#0000ff">/home/jiang/tools/httpd-2.0.59</font>，</font>
<font color="#0000ff" size="2">/home/jiang/tools/mysql-5.0.16</font>
<font size="2">和</font>
<font size="2">
<font color="#0000ff">/home/jiang/tools/php-5.1.4</font>。而且它们的安装目标路径分别为：<font color="#0000ff">/usr/local/apache2</font>，<font color="#0000ff">/usr/local/mysql5</font>和<font color="#0000ff">/usr/local/php5</font>。</font>
<br />
<font size="2">
<strong>1. 安装Apache2</strong>
<br />
进入</font>
<font size="2">
<font color="#0000ff">/home/jiang/tools/httpd-2.0.59</font>目录，执行如下命令：</font>
<br />
<font color="#0000ff" size="2">#./configure<br />
--prefix=</font><font color="#0000ff" size="2">/usr/local/apache2<font color="#000000">&nbsp; -- 设置Apache安装目标目录</font></font>
<font color="#0000ff">
<br />
</font>
<font size="2">
<font color="#0000ff">--enable-so<br />
--enable-vhost-alias<br />
--enable-rewrite<br />
--enable-deflate<br />
--with-mpm=worker<br />
#make<br />
#make install</font>
<br />
编辑文件/usr/local/apache2/conf/httpd.conf：<br />
[1]查找元素<font color="#0000ff">DocumentRoot</font>，它的值默认为/usr/local/apache2/htdocs<br />
[2]查找元素<font color="#0000ff">DirectoryIndex</font>，在这一项可以添加实际应用中需要的首页文件名<br />
<br />
启动/关闭Apache服务器：<br />
进入<font color="#0000ff">/usr/local/apache2/bin</font>目录，执行命令<font color="#0000ff">./apachectl start</font>(启动服务器)或<font color="#0000ff">./apachectl stop</font>(关闭服务器)。<br />
<br />
<strong>2. 安装MySQL5</strong><br />
<font color="#0000ff">#</font></font>
<font color="#0000ff">
</font>
<font color="#0000ff" size="2">groupadd </font>
<font color="#0000ff" size="2">mysql<font color="#000000">&nbsp; -- 添加组mysql</font><br />
#</font>
<font color="#0000ff">
</font>
<font color="#0000ff" size="2">useradd </font>
<font color="#0000ff" size="2">-g mysql mysql<font color="#000000">&nbsp; -- 添加用户mysql，并将它放入组mysql中</font><br />
<font color="#000000">进入</font></font>
<font color="#000000" size="2">
<font color="#0000ff">/home/jiang/tools/mysql-5.0.16</font>目录，执行如下命令：</font>
<font color="#0000ff">
<br />
</font>
<font size="2">
<font color="#0000ff">#./configure<br />
--prefix=/path_to_mysql5<font color="#000000">&nbsp; -- 设置MySQL安装目标目录</font><br />
--with-charset=utf8<font color="#000000">&nbsp; -- 设置默认字符集为utf8</font><br />
#make<br />
#make install<br />
#./scripts/mysql_install_db<font color="#000000">&nbsp; -- 初始化MySQL数据库</font><br />
<font color="#000000">进入<font color="#0000ff">/usr/local</font>目录，执行如下命令：</font><br />
#chown -R mysql.mysql mysql5<font color="#000000"> -- 将/usr/local/mysql5目录及其子目录的属主赋予mysql用户</font></font>
<br />
在<font color="#0000ff">/home/jiang/tools/mysql-5.0.16/support-files</font></font>
<font size="2">目录</font>
<font size="2">中选择一个合适的<font color="#0000ff">.cnf</font>文件放入<font color="#0000ff">/etc</font>目录中，并将文件修改为<font color="#0000ff">my.cnf</font>。然后编辑该文件，使它更能切合实际的应用。<br />
<br />
启动/关闭服务器：<br />
进入<font color="#0000ff">/usr/local/mysql5/bin</font>目录，执行命令<font color="#0000ff">./mysqld_safe -u mysql</font>(用mysql用户启动服务器)或<font color="#0000ff">./mysqladmin -uroot shutdown</font>(关闭服务器)。<br />
<br />
<strong>3. 安装PHP5</strong><br />
<font color="#0000ff"><font color="#000000">进入/home/jiang/tools/php-5.1.4目录，执行如下命令：</font><br />
#./configure<br />
--prefix=/usr/local/php5<br />
--enable-mbstring<font color="#000000">&nbsp; -- 根据应用的需要，添加mbstring模块</font><br />
--with-apxs2=/usr/local/apache2/bin/apxs<br />
--with-apache2=/home/jiang/tools/httpd-2.0.59<br />
--with-png<br />
--with-zlib<br />
--with-config-file-path=/usr/local/php5/lib<br />
--with-mysql=/usr/local/mysql5<br />
--with-mysqli=/home/jiang/tools/mysql-5.0.16/scripts/mysql_config<font color="#000000">&nbsp; -- 根据应用的需要，添加mysqli模块</font></font><br />
<font color="#0000ff">#make<br />
#make install</font><br />
将<font color="#0000ff">/home/jiang/tools/php-5.1.4/php.ini-recommended</font>文件放入<font color="#0000ff">/usr/local/php5/lib</font>目录中，并将文件名修改为<font color="#0000ff">php.ini</font>。<br />
查看<span style="color: #0010ff;">/usr/local/php5/lib/php.ini</span>文件，看参数<span style="color: #0010ff;">short_open_tag</span>的值是否为<span style="color: #0010ff;">On</span>。如果是<span style="color: #0010ff;">Off</span>，请修改为<span style="color: #0010ff;">On</span>。<br />
<br />
查看<font color="#0000ff">/usr/local/apache2/conf/httpd.conf</font>文件，看是否存在语句：<br />
<font color="#0000ff">LoadModule php5_module&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; modules/libphp5.so</font><br />
如果存在，即说明apache已经成功加载了php模块；<br />
并添加如下两条语句(否则PHP页面可能无法被解析)：<br />
<span style="color: #0010ff;">AddType application/x-httpd-php .php</span><br style="color: #0010ff;" />
<span style="color: #0010ff;">AddType application/x-httpd-php-source .phps</span><br />
</font><img src ="http://www.blogjava.net/jiangshachina/aggbug/91369.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangshachina/" target="_blank">Sha Jiang</a> 2007-01-02 13:48 <a href="http://www.blogjava.net/jiangshachina/archive/2007/01/02/91369.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Maven入门--较复杂的实例(原)</title><link>http://www.blogjava.net/jiangshachina/archive/2006/12/12/79093.html</link><dc:creator>Sha Jiang</dc:creator><author>Sha Jiang</author><pubDate>Tue, 12 Dec 2006 10:03:00 GMT</pubDate><guid>http://www.blogjava.net/jiangshachina/archive/2006/12/12/79093.html</guid><wfw:comment>http://www.blogjava.net/jiangshachina/comments/79093.html</wfw:comment><comments>http://www.blogjava.net/jiangshachina/archive/2006/12/12/79093.html#Feedback</comments><slash:comments>21</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangshachina/comments/commentRss/79093.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangshachina/services/trackbacks/79093.html</trackback:ping><description><![CDATA[<div align="center"><font size="4"><strong><span style="font-size: 14pt;">Maven入门--较复杂的实例</span></strong> </font><br />
</div>
<font size="2"><font size="2">本文将使用一个较复杂的实例，讲述如何定制目录布局(即不使用Maven标准目录布局)，以及讲述一些关键插件的使用(配置)。为了方便其它朋友能够方便地使用该实例，后台数据库使用开源的面向对象数据库--<a href="http://www.db4o.com/">db4o</a>，该数据库无需安装，已包含在与本文配套的实例中，文末附有该实例的下载链接。(2007.01.02最后更新)<br />
<span style="font-size: 12pt; color: red;"><span style="font-size: 12pt; color: red;">注：转载时请注明原作者(jiangshachina)及出处(<a style="color: red;" href="http://www.blogjava.net/jiangshachina">http://www.blogjava.net/jiangshachina</a>)！</span></span><br />
<br />
<strong><font size="3">1 实例的构想</font></strong><br />
文章开头的摘要已经讲述了，本文仍然将以一个实例描述如何使用Maven，</font> <font size="2">该实例将使用非Maven标准的目录结构，并将呈现一些关键的Maven插件的配置与应用。</font> <font size="2">该实例是一个基于db4o的数据库Web应用。该应用本身十分简单，即从db4o数据库中查询出若干记录并将它们显现在Web页面中。<br />
</font><font size="2">&nbsp;&nbsp;&nbsp; 该实例仍然由一个普通应用工程(demo-app)与一个Web应用工程(demo-web)，以及这两个工程的父工程(demo)构成，最终的目标是将Web应用工程制作成war文件，并部署到JBoss服务器中。启动服务器后，能够在页面中看到正确的查询结果。</font> <br />
<font size="2">&nbsp;&nbsp;&nbsp; 该实例使用<font color="#008000">Eclipse3.2 + JDK1.5.0_10 + Windows2000</font>开发。当然这仅仅只是我个人的开发平台，但该实例并不受限于此平台；由于我选择使用db4o针对JDK1.5的产品包，所以该实例只能运行在JDK1.5.0或更高版本的JDK/JRE中；</font> <font size="2">该工程中的所有文件都使用<font color="#006400">UTF-8</font>编码方式。</font> <br />
<font size="2"><br />
<font size="3"><strong>2 demo工程</strong> </font><br />
demo工程是其它两个工程的父工程，它的主要职责是预定义子工程所需要依赖的jar文件(artifact)，以及针对子工程所使用的插件进行通用配置。该工程完整的POM文件如下所示：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">&lt;project</span><span style="color: #000000;">&gt;<br />
</span></font></font></font></font></font></font><span style="color: #000000;">&nbsp;&nbsp;&nbsp; &lt;modelVersion&gt;</span><span style="color: #000000;">4.0.0</span><span style="color: #000000;">&lt;/modelVersion&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;groupId&gt;mvn.demo&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;demo&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;packaging&gt;pom&lt;/packaging&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;version&gt;</span><span style="color: #000000;">1.0</span><span style="color: #000000;">-SNAPSHOT&lt;/version&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;description&gt;Maven&nbsp;Demo&nbsp;Project&lt;/description&gt;<br />
<br />
&nbsp;&nbsp;&nbsp; &lt;modules&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;module&gt;demo-app&lt;/module&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;module&gt;demo-web&lt;/module&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/modules&gt;<br />
<br />
&nbsp;&nbsp;&nbsp; &lt;dependencyManagement&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;dependencies&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;dependency&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;mvn.demo&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;demo-app&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;version&gt;${project.version}&lt;/version&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/dependency&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;dependency&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;mvn.demo&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;demo-web&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;version&gt;${project.version}&lt;/version&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/dependency&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;dependency&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;com.db4o&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;db4o-java5&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;version&gt;</span><span style="color: #000000;">5.5</span><span style="color: #000000;">&lt;/version&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/dependency&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;dependency&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;javax.servlet&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;servlet-api&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;version&gt;</span><span style="color: #000000;">2.4</span><span style="color: #000000;">&lt;/version&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;scope&gt;provided&lt;/scope&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/dependency&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;dependency&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;commons-configuration&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;commons-configuration&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;version&gt;</span><span style="color: #000000;">1.2</span><span style="color: #000000;">&lt;/version&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;exclusions&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;exclusion&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;dom4j&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;dom4j&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/exclusion&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;exclusion&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;xml-apis&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;xml-apis&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/exclusion&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;exclusion&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;xalan&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;xalan&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/exclusion&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;exclusion&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;xerces&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;xercesImpl&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/exclusion&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/exclusions&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/dependency&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/dependencies&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/dependencyManagement&gt;<br />
<br />
&nbsp;&nbsp;&nbsp; &lt;dependencies&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;dependency&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;junit&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;junit&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;version&gt;</span><span style="color: #000000;">3.8.1</span><span style="color: #000000;">&lt;/version&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;scope&gt;test&lt;/scope&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/dependency&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/dependencies&gt;<br />
<br />
&nbsp;&nbsp;&nbsp; &lt;build&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;plugins&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;plugin&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;maven-resources-plugin&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;encoding&gt;UTF-</span><span style="color: #000000;">8</span><span style="color: #000000;">&lt;/encoding&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/plugin&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;plugin&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;source&gt;</span><span style="color: #000000;">1.5</span><span style="color: #000000;">&lt;/source&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;target&gt;</span><span style="color: #000000;">1.5</span><span style="color: #000000;">&lt;/target&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;encoding&gt;UTF-</span><span style="color: #000000;">8</span><span style="color: #000000;">&lt;/encoding&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/plugin&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;plugin&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;maven-jar-plugin&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;archive&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;addMavenDescriptor&gt;false&lt;/addMavenDescriptor&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/archive&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/plugin&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;plugin&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;archive&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;addMavenDescriptor&gt;false&lt;/addMavenDescriptor&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/archive&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/plugin&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;plugin&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;artifactId&gt;maven-javadoc-plugin&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;charset&gt;UTF16&lt;/charset&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/plugin&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/plugins&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/build&gt;<br />
&lt;/project&gt;<img src="http://www.blogjava.net/Images/OutliningIndicators/None.gif" alt="" align="top" /></span></div>
&nbsp;&nbsp;&nbsp; 预定义工程的依赖关系，就是把会被子工程依赖的artifact的详细信息(groupId，artifactId，version，...)先声明到&lt;dependencyManagement&gt;中。然后子工程只需要声明使用某个artifact就可以了，即那时只需要设置groupId和artifactId(甚至更少)就可以了。</font> <font size="2"><strong>&lt;dependencyManagement&gt;中声明的artifact并不一定真的会被使用到</strong>。</font> <br />
<font size="2"><strong>2.1 声明依赖关系</strong> <br />
&nbsp;&nbsp;&nbsp; 根据实际情况，</font> <font size="2">该实例</font> <font size="2">需要使用db4o针对java5的产品包(jar文件)。由于该jar文件并不存在于Maven的中央仓库中，所以我们不能直接通过Maven获得该jar文件。我们只能另外下载db4o-5.5(Java版)的压缩包，然后从压缩包内获得db4o-java5.jar。得到该jar后，必须先将它安装到Maven的本地仓库中(安装方法参见资源[1]，主题"向本地仓库安装文件时要生成POM文件")，以备后面的使用。此处将该artifact的groupId定义为<font color="#0000ff">com.db4o</font>，artifactId定义为<font color="#0000ff">db4o-java5</font>，version自然就是5.5了(请见上述POM脚本)。<br />
</font><font size="2">&nbsp;&nbsp;&nbsp; 由于该实例最终是一个Web应用，所以它至少需要依赖Servlet的包(servlet-api-2.4.jar)，还需要commons-configuration-1.2.jar。这两个artifact都已经存在于Maven中央仓库中，所以我查找到它们后，按照Maven中央仓库的命名将它们声明到了&lt;dependencyManagement&gt;中(请见上述POM脚本)。junit是进行单元测试时使用的artifact，(假设)它肯定会被每个工程使用，所以没有将它设置到</font> <font size="2">&lt;dependencyManagement&gt;中，而直接设置到了</font> <font size="2">&lt;dependency&gt;中。</font> <br />
<font size="2">&nbsp;&nbsp;&nbsp; 细心的朋友肯定已经发现了，针对</font> <font size="2">commons-configuration的依赖声明处多了一些语句。从表面上看，应该是排除了4个artifact(dom4j，</font> <font size="-0"><font size="2"><span style="color: #000000;">xml-apis</span> </font></font><font size="2">，</font> <font size="-0"><font size="2"><span style="color: #000000;">xalan</span> </font></font><font size="2">和</font> <font size="-0"><font size="2"><span style="color: #000000;">xerces</span> </font></font><font size="2">)。不错，就是排除了这4个jar文件(artifact)。如果有兴趣的话，可以将整个&lt;exclusions&gt;元素删除，然后再尝试一下制作war文件。你会发现在WEB-INF/lib目录下存在着这4个artifact对应的jar文件。那我为什么要将它们&#8220;排除&#8221;呢？因为，它们是多余的！即，它们对于我的这个Web应用来说，根本就是无用的！<br />
&nbsp;&nbsp;&nbsp; Maven2加入了一个很好的特性：<strong>自动加载&#8220;依赖的依赖(Transitive Dependency)&#8221;</strong>。以commons-configuration为例。为了能够让它运行正常，我们实际上还需要其它一些jar(artifact)，如commons-collections，commons-lang，...。但这些artifact我都没有&#8220;显示&#8221;地声明需要依赖它们，但Maven会自动加载，因为</font> <font size="2">commons-configuration的POM文件将它们声明为了dependency</font> <font size="2">。<br />
&nbsp;&nbsp;&nbsp; 既然那个4个artifact是<font size="2">commons-configuration的依赖，为什么会认为它们是无用的呢？实际上，它们就不应该被声明到</font><font size="2">commons-configuration的依赖关系中。这是</font><font size="2">commons-configuration开发者的失误，他们没有将依赖关系整理清晰，而将一些确实既不是runtime，更不是compile-time需要的artifact放入到了依赖关系中。在Maven中央仓库中存在着很多这种情况，所以我们有时需要弄清楚&#8220;哪些文件是我们真正需要的，哪些是可以被清除的&#8221;。但有时候，很难做到一个不漏。正是由于这一原因，自动加载Transitive Dependency这一极好的特性，有时让人十分无奈 ^_^<br />
<strong>2.2 对插件进行基本配置</strong><br />
我们可以把对插件的全局性(如针对整个项目的)设置放到较高层次的POM文件中，因为它们被设置后，子工程们就会自然遵守它们，而且可以使每个子工程的情况都是一样的。<br />
&nbsp;&nbsp;&nbsp; 在第1节中，已经表明该工程使用JDK1.5平台，并且所有文件都使用UTF-8</font><font size="2">的编码方式</font><font size="2">。而Maven默认使用JDK1.3级别的javac编译器；默认使用本地编码方式(简体中文Windows操作系统默认使用GBK编码方式)处理文件。这样就必须对Maven进行适当设置，以满足工程的实际需要。<br />
</font><font size="2">&nbsp;&nbsp;&nbsp; 针对资源文件的处理<font color="#000000">，Maven使用maven-resources-plugin插件，需要将它的编码方式设置为UTF-8。编译Java源文件，是使用maven-compiler-plugin插件，需要将它的source(Java源文件)与target(class文件)的级别都设置为1.5，另外还要将它的encoding方式设置为UTF-8。（详细设置请见POM脚本）</font><br />
<br />
<strong><font size="3">3 demo-app工程</font><br />
</strong>demo-app工程是一个普通应用程序工程，它用于处理和数据库相关的操作，如针对数据库的增、删、改、查等基本功能。该工程POM文件的主要内容如下所示：<br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><span style="color: #000000;">&lt;project</span><span style="color: #000000;">&gt;<br />
&nbsp;&nbsp;&nbsp; ......</span><span style="color: #000000;"><br />
&nbsp;&nbsp;&nbsp; &lt;build&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;finalName&gt;app&lt;/finalName&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;directory&gt;target&lt;/directory&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;sourceDirectory&gt;src/java&lt;/sourceDirectory&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;outputDirectory&gt;target/classes&lt;/outputDirectory&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;resources&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;resource&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;directory&gt;src/java&lt;/directory&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;excludes&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;exclude&gt;**/*.java&lt;/exclude&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/excludes&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/resource&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/resources&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;testSourceDirectory&gt;src/test/java&lt;/testSourceDirectory&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;testOutputDirectory&gt;target/test-classes&lt;/testOutputDirectory&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;testResources&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;testResource&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;directory&gt;src/test/java&lt;/directory&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;excludes&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;exclude&gt;**/*.java&lt;/exclude&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/excludes&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/testResource&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/testResources&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/build&gt;<br />
&lt;/project&gt;<br />
</span></div>
&nbsp;&nbsp;&nbsp; 文章的开头已经提到，本实例将会使用定制的目录结构，但在前面却一字不提此事，现在将描述如何定制目录结构。Maven的标准目录结构其实是在Super POM中设置的，由于任何POM都会继承该POM，所以所有的工作都会默认使用标准目录结构。要定制目录，其实就是需要重新设置相关参数的值，即用新值覆盖Super POM中的值。<br />
</font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">[1]&lt;finalName&gt;，该元素指定了工程输出的artifact的名称，默认值为${artifactId}-${version}，此处修改为app。<br />
</span></font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">[2]&lt;directory&gt;，该元素指定了工程输出的目标目录。默认值为target，此处未修改变。<br />
</span></font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">[3]&lt;sourceDirectory&gt;，该元素指定了Java源文件所在的目录。默认值为src/main/java，此处修改为src/java。<br />
</span></font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">[4]&lt;outputDirectory&gt;，该元素指定了编译后的class文件的放置目录。默认值为target/classes，此处未作改变。<br />
</span></font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">[5]&lt;resources&gt;</span> </font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">&lt;resource&gt;，该元素指定了Java源文件使用的资源文件的存放目录。默认值为src/main/resources，此处修改为src/java。由于在编码Java源文件时，Maven会将资源路径中的文件全部拷贝到classes目录。而此时将Java资源文件目录与Java源文件目录，设置为同一目录，所以需要将.java文件排除在资源文件的范畴之外(</span> </font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">&lt;exclude&gt;**/*.java&lt;/exclude&gt;</span> </font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">)。<br />
[6]</span> </font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">&lt;testSourceDirectory&gt;，该元素指定了单元测试Java源文件的放置目录。默认值为src/test/java，此处未作修改。<br />
[7]</span> </font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">&lt;testOutputDirectory&gt;，该元素指定了单元测试Java源文件编译后的class文件放置目录。默认值为</span> </font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">target/test-classes，此处未作改变。<br />
[8]</span> </font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">&lt;testResources&gt;</span> </font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">&lt;testResource&gt;，该元素指定了单元测试Java源文件所使用的资源文件的放置目录。默认值为src/test/resources，此处修改为</span> </font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">src/test/java。并且也做了与</span> </font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">设置&lt;resources&gt;</span> </font></font></font></font></font></font><font size="-0"><font size="-0"><font size="-0"><font size="2"><font size="2"><font size="2"><span style="color: #000000;">&lt;resource&gt;时相同的处理(排除Java源文件)。<br />
&nbsp;&nbsp;&nbsp; 通过上述设置后，就可以拥有一个定制的Maven工程目录结构了。<br />
</span></font></font></font></font></font></font><font size="2"><font size="2"><font size="2"><br />
</font></font><font size="3"><strong>4 demo-web工程<br />
</strong></font>demo-web工程是整个应用最终的目标输出，因为此处的目的就是制作一个war文件，然后将它部署到JBoss服务器中。与demo-app工程相比，demo-web工程的POM文件主要有如下不同内容：<br />
</font>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #000000;">&lt;project</span> <span style="color: #000000;">&gt;<br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp; ......<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;build&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ......<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;plugins&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;plugin&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;artifactId&gt;maven-war-plugin&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;version&gt;</span> <span style="color: #000000;">2.0.1</span> <span style="color: #000000;">&lt;/version&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;webappDirectory&gt;target/${artifactId}&lt;/webappDirectory&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;warSourceDirectory&gt;src/webapp&lt;/warSourceDirectory&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/plugin&gt;<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;plugin&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;artifactId&gt;jboss-maven-plugin&lt;/artifactId&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;version&gt;</span> <span style="color: #000000;">1.3.1</span> <span style="color: #000000;">&lt;/version&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;jbossHome&gt;E:/jboss-</span> <span style="color: #000000;">4.0.2</span> <span style="color: #000000;">&lt;/jbossHome&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;serverName&gt;default&lt;/serverName&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;fileName&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;${project.build.directory}/${project.build.finalName}.${project.packaging}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/fileName&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/configuration&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/plugin&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/plugins&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/build&gt;<br />
&lt;/project&gt;</span> </div>
<font size="2"><font size="2">可以看出不同之处就在于对maven-war-plguin及jboss-maven-plugin插件的配置与使用。<br />
&nbsp;&nbsp;&nbsp; Maven使用maven-war-plugin插件对Web工程制作war文件。由于本文使用了定制目录结构，这样则会使maven-war-plugin无法找到Web工程的Web Root目录(默认是src/main/webapp)，所以需要对该插件进行适当地配置。&lt;warSourceDirectory&gt;就是Web工程的Web Root目录，此处设置为；&lt;webappDirectory&gt;是制作war文件之前，相当于是一个被打开(exploded)的war文件的根目录(默认是target/artifactId-version)。<br />
&nbsp;&nbsp;&nbsp; 该工程的脚本中，还使用了一个JBoss插件。该插件可以将制作好的war文件部署(实质上是拷贝)到指定的JBoss部署目录中。&lt;jbossHome&gt;是JBoss的安装根目录，&lt;serverName&gt;指JBoss Server的名称，&lt;fileName&gt;是被部署war文件的名称。<br />
<br />
<font size="3"><strong>参考资源</strong></font><br />
[1]Maven入门--概念与实例. http://www.blogjava.net/jiangshachina/archive/2006/09/01/67080.html<br />
[2]Maven + Continuum Weed. http://www.blogjava.net/jiangshachina/archive/2006/09/11/68944.aspx<br />
[3]Maven POM Reference. http://maven.apache.org/pom.html<br />
[3]db4o. http://www.db4objects.com<br />
<font size="3"><strong>本文实例下载地址--</strong></font><a href="http://www.blogjava.net/files/jiangshachina/mvn-demo.rar"><font size="3"><strong>http://www.blogjava.net/files/jiangshachina/mvn-demo.rar</strong></font><br />
<br />
</a></font></font><img src ="http://www.blogjava.net/jiangshachina/aggbug/79093.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangshachina/" target="_blank">Sha Jiang</a> 2006-12-12 18:03 <a href="http://www.blogjava.net/jiangshachina/archive/2006/12/12/79093.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle Weed(原)</title><link>http://www.blogjava.net/jiangshachina/archive/2006/08/12/63121.html</link><dc:creator>Sha Jiang</dc:creator><author>Sha Jiang</author><pubDate>Sat, 12 Aug 2006 01:22:00 GMT</pubDate><guid>http://www.blogjava.net/jiangshachina/archive/2006/08/12/63121.html</guid><wfw:comment>http://www.blogjava.net/jiangshachina/comments/63121.html</wfw:comment><comments>http://www.blogjava.net/jiangshachina/archive/2006/08/12/63121.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangshachina/comments/commentRss/63121.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangshachina/services/trackbacks/63121.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 学习使用Oracle的过程中，收集的一些小知识。不断更新中...&nbsp;&nbsp;<a href='http://www.blogjava.net/jiangshachina/archive/2006/08/12/63121.html'>阅读全文</a><img src ="http://www.blogjava.net/jiangshachina/aggbug/63121.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangshachina/" target="_blank">Sha Jiang</a> 2006-08-12 09:22 <a href="http://www.blogjava.net/jiangshachina/archive/2006/08/12/63121.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MySQL Weed(原)</title><link>http://www.blogjava.net/jiangshachina/archive/2006/08/12/63120.html</link><dc:creator>Sha Jiang</dc:creator><author>Sha Jiang</author><pubDate>Sat, 12 Aug 2006 01:19:00 GMT</pubDate><guid>http://www.blogjava.net/jiangshachina/archive/2006/08/12/63120.html</guid><wfw:comment>http://www.blogjava.net/jiangshachina/comments/63120.html</wfw:comment><comments>http://www.blogjava.net/jiangshachina/archive/2006/08/12/63120.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangshachina/comments/commentRss/63120.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangshachina/services/trackbacks/63120.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在学习、应用MySQL的过程中，收集的一些小知识。(2007.09.04最后更新)&nbsp;&nbsp;<a href='http://www.blogjava.net/jiangshachina/archive/2006/08/12/63120.html'>阅读全文</a><img src ="http://www.blogjava.net/jiangshachina/aggbug/63120.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangshachina/" target="_blank">Sha Jiang</a> 2006-08-12 09:19 <a href="http://www.blogjava.net/jiangshachina/archive/2006/08/12/63120.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Linux上安装MySQL Server 5.0(原)</title><link>http://www.blogjava.net/jiangshachina/archive/2006/08/12/63117.html</link><dc:creator>Sha Jiang</dc:creator><author>Sha Jiang</author><pubDate>Sat, 12 Aug 2006 01:10:00 GMT</pubDate><guid>http://www.blogjava.net/jiangshachina/archive/2006/08/12/63117.html</guid><wfw:comment>http://www.blogjava.net/jiangshachina/comments/63117.html</wfw:comment><comments>http://www.blogjava.net/jiangshachina/archive/2006/08/12/63117.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangshachina/comments/commentRss/63117.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangshachina/services/trackbacks/63117.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 本人安装MySQL Server 5.0的过程与体会，希望对大家有帮助。&nbsp;&nbsp;<a href='http://www.blogjava.net/jiangshachina/archive/2006/08/12/63117.html'>阅读全文</a><img src ="http://www.blogjava.net/jiangshachina/aggbug/63117.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangshachina/" target="_blank">Sha Jiang</a> 2006-08-12 09:10 <a href="http://www.blogjava.net/jiangshachina/archive/2006/08/12/63117.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Linux上安装Oracle10g(原)</title><link>http://www.blogjava.net/jiangshachina/archive/2006/08/11/63050.html</link><dc:creator>Sha Jiang</dc:creator><author>Sha Jiang</author><pubDate>Fri, 11 Aug 2006 09:06:00 GMT</pubDate><guid>http://www.blogjava.net/jiangshachina/archive/2006/08/11/63050.html</guid><wfw:comment>http://www.blogjava.net/jiangshachina/comments/63050.html</wfw:comment><comments>http://www.blogjava.net/jiangshachina/archive/2006/08/11/63050.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jiangshachina/comments/commentRss/63050.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jiangshachina/services/trackbacks/63050.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要:     因工作原由，这一段时间学习了在Linux上安装Oracle。在这一过程中有不少的收获，写出此文与大家共享。不同版本Oracle的安装应该没有本质上的区别，本文也可供大家在安装Oracle9.2和Oracle10.2时进行参考。<br>    其实我对Linux和Oracle都不熟悉，在实际的安装过程中，还有许多不明白的地方，经常是“知其然，而不知其所以然”。如，为什么要配置kernel参数？相关kernel参数分别有什么作用？设置临时交换空间所用的命令dd的功能是什么？......希望有朋友能够针对其中的问题进行解答。如果文中有什么错误，也请大家指正。<br>&nbsp;&nbsp;<a href='http://www.blogjava.net/jiangshachina/archive/2006/08/11/63050.html'>阅读全文</a><img src ="http://www.blogjava.net/jiangshachina/aggbug/63050.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jiangshachina/" target="_blank">Sha Jiang</a> 2006-08-11 17:06 <a href="http://www.blogjava.net/jiangshachina/archive/2006/08/11/63050.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>