<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>crabboy</title>
    <description></description>
    <link>http://crabboy.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>oracle中的字符集问题</title>
        <author>crabboy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://crabboy.javaeye.com">crabboy</a>&nbsp;
          链接：<a href="http://crabboy.javaeye.com/blog/216586" style="color:red;">http://crabboy.javaeye.com/blog/216586</a>&nbsp;
          发表时间: 2008年07月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Oracle字符集问题<br /><br />一．引言 <br /><br />    ORACLE数据库字符集，即Oracle全球化支持(Globalization Support)，或即国家语言支持（NLS）其作用是用本国语言和格式来存储、处理和检索数据。利用全球化支持，ORACLE为用户提供自己熟悉的数据库母语环境，诸如日期格式、数字格式和存储序列等。Oracle可以支持多种语言及字符集，其中oracle8i支持48种语言、76个国家地域、229 种字符集，而oracle9i则支持57种语言、88个国家地域、235种字符集。由于oracle字符集种类多，且在存储、检索、迁移oracle数据时多个环节与字符集的设置密切相关，因此在实际的应用中，数据库开发和管理人员经常会遇到有关oracle字符集方面的问题。本文通过以下几个方面阐述，对oracle字符集做简要分析<br /><br /> <br /><br />二．字符集基本知识<br /><br /> <br /><br />2.1字符集<br /><br />    实质就是按照一定的字符编码方案，对一组特定的符号，分别赋予不同数值编码的集合。Oracle数据库最早支持的编码方案是US7ASCII。<br />    Oracle的字符集命名遵循以下命名规则:<br />    &lt;Language>&lt;bit size>&lt;encoding><br />    即:  &lt;语言>&lt;比特位数>&lt;编码><br />    比如: ZHS16GBK表示采用GBK编码格式、16位（两个字节）简体中文字符集<br /><br /> <br /><br />2.2字符编码方案<br /><br />2.2.1 单字节编码<br />    （1）单字节7位字符集，可以定义128个字符，最常用的字符集为US7ASCII<br />    （2）单字节8位字符集，可以定义256个字符，适合于欧洲大部分国家<br />              例如：WE8ISO8859P1(西欧、8位、ISO标准8859P1编码)，iso8859-1 都应用于英文系列．<br />2.2.2 多字节编码<br />    （1）变长多字节编码<br />              某些字符用一个字节表示，其它字符用两个或多个字符表示，变长多字节编码常用于对亚洲语言的支持，   例如日语、汉语、印地语等<br />              例如：AL32UTF8（其中AL代表ALL,指适用于所有语言）、zhs16cgb231280<br />    （2）定长多字节编码<br />              每一个字符都使用固定长度字节的编码方案，目前oracle唯一支持的定长多字节编码是AF16UTF16，也仅用于国家字符集2.2.3 unicode编码<br />              Unicode是一个涵盖了目前全世界使用的所有已知字符的单一编码方案，也就是说Unicode为每一个字符提供唯一的编码。UTF-16是 unicode的16位编码方式，是一种定长多字节编码，用2个字节表示一个unicode字符，AF16UTF16是UTF-16编码字符集。<br />              UTF-8是unicode的8位编码方式，是一种变长多字节编码，这种编码可以用1、2、3个字节表示一个unicode字符，AL32UTF8，UTF8、UTFE是UTF-8编码字符集。<br /><br />　　下面介绍几钟常用的字符编码集：　　<br /><br />　　iso8859-1<br /><br />　　属于单字节编码，最多能表示的字符范围是0-255，应用于英文系列。比如，字母'a'的编码为0x61=97。很明显，iso8859-1编码表示的字符范围很窄，无法表示中文字符。但是，由于是单字节编码，和计算机最基础的表示单位一致，所以很多时候，仍旧使用iso8859-1编码来表示。而且在很多协议上，默认使用该编码。比如，虽然"中文"两个字不存在iso8859-1编码，以gb2312编码为例，应该是"d6d0 cec4"两个字符，使用iso8859-1编码的时候则将它拆开为4个字节来表示："d6 d0 ce c4"（事实上，在进行存储的时候，也是以字节为单位处理的）。而如果是UTF编码，则是6个字节"e4 b8 ad e6 96 87"。很明显，这种表示方法还需要以另一种编码为基础。<br /><br />　　GB2312/GBK<br /><br />　　这就是汉字的国标码，专门用来表示汉字，是双字节编码，而英文字母和iso8859-1一致（兼容iso8859-1编码）。其中gbk编码能够用来同时表示繁体字和简体字，而gb2312只能表示简体字，gbk是兼容gb2312编码的。<br /><br />         unicode<br /><br />        这是最统一的编码，可以用来表示所有语言的字符，而且是定长双字节（也有四字节的）编码，包括英文字母在内。所以可以说它是不兼iso8859-1编码的，也不兼容任何编码。不过，相对于iso8859-1编码来说，uniocode编码只是在前面增加了一个0字节，比如字母'a'为"00 61"。需要说明的是，定长编码便于计算机处理（注意GB2312/GBK不是定长编码），而unicode又可以用来表示所有字符，所以在很多软件内部是使用unicode编码来处理的，比如java。<br /><br />         UTF<br /><br />         考虑到unicode编码不兼容iso8859-1编码，而且容易占用更多的空间：因为对于英文字母，unicode也需要两个字节来表示。所以 unicode不便于传输和存储。因此而产生了utf编码，utf编码兼容iso8859-1编码，同时也可以用来表示所有语言的字符，不过，utf编码是不定长编码，每一个字符的长度从1-6个字节不等。另外，utf编码自带简单的校验功能。一般来讲，英文字母都是用一个字节表示，而汉字使用三个字节。注意，虽然说utf是为了使用更少的空间而使用的，但那只是相对于unicode编码来说，如果已经知道是汉字，则使用GB2312/GBK无疑是最节省的。不过另一方面，值得说明的是，虽然utf编码对汉字使用3个字节，但即使对于汉字网页，utf编码也会比unicode编码节省，因为网页中包含了很多的英文字符。<br /><br /> <br /><br />2.3 字符集超级<br /><br />              当一种字符集（字符集A）的编码数值包含所有另一种字符集（字符集B）的编码数值，并且两种字符集相同编码数值代表相同的字符时，则字符集A是字符集B的超级，或称字符集B是字符集A的子集。<br />              Oracle8i和oracle9i官方文档资料中备有子集-超级对照表（subset-superset pairs），例如：WE8ISO8859P1是WE8MSWIN1252的子集。由于US7ASCII是最早的Oracle数据库编码格式，因此有许多字符集是US7ASCII的超集，例如WE8ISO8859P1、ZHS16CGB231280、ZHS16GBK都是US7ASCII的超集。<br /><br /> <br /><br />2.4 数据库字符集（oracle服务器端字符集）<br /><br />     数据库字符集在创建数据库时指定，在创建后通常不能更改。在创建数据库时，可以指定字符集(CHARACTER SET)和国家字符集(NATIONAL CHARACTER SET)。<br /><br />2.4.1字符集<br />    (1)用来存储CHAR, VARCHAR2, CLOB, LONG等类型数据<br />    (2)用来标示诸如表名、列名以及PL/SQL变量等<br />    (3)用来存储SQL和PL/SQL程序单元等<br /><br />2.4.2国家字符集：<br />    (1)用以存储NCHAR, NVARCHAR2, NCLOB等类型数据<br />    (2)国家字符集实质上是为oracle选择的附加字符集，主要作用是为了增强oracle的字符处理能力，因为NCHAR数据类型可以提供对亚洲使用定长多字节编码的支持，而数据库字符集则不能。国家字符集在oracle9i中进行了重新定义，只能在unicode编码中的AF16UTF16和UTF8 中选择，默认值是AF16UTF16<br /><br />2.4.3查询字符集参数<br />    可以查询以下数据字典或视图查看字符集设置情况<br />    nls_database_parameters、props$、v$nls_parameters<br />    查询结果中NLS_CHARACTERSET表示字符集，NLS_NCHAR_CHARACTERSET表示国家字符集<br /><br />2.4.4修改数据库字符集<br />    按照上文所说，数据库字符集在创建后原则上不能更改。如果需要修改字符集，通常需要导出数据库数据，重建数据库，再导入数据库数据的方式来转换，或通过 ALTER DATABASE CHARACTER SET语句修改字符集，但创建数据库后修改字符集是有限制的，只有新的字符集是当前字符集的超集时才能修改数据库字符集，例如UTF8是US7ASCII 的超集，修改数据库字符集可使用ALTER DATABASE CHARACTER SET UTF8。<br />2.4.5查询Oracle Server端字符集<br />     SQL>select userenv(‘language’) from dual;<br /><br /> <br /><br />2.5 客户端字符集（NLS_LANG参数）<br /><br />2.5.1客户端字符集含义<br />    客户端字符集定义了客户端字符数据的编码方式，任何发自或发往客户端的字符数据均使用客户端定义的字符集编码,客户端可以看作是能与数据库直接连接的各种应用，例如sqlplus,exp/imp等。客户端字符集是通过设置NLS_LANG参数来设定的。<br /><br />2.5.2 NLS_LANG参数格式<br />    NLS_LANG=&lt;language>_&lt;territory>.&lt;client character set><br />    Language:显示oracle消息,校验，日期命名<br />    Territory：指定默认日期、数字、货币等格式<br />    Client character set：指定客户端将使用的字符集<br />    例如：NLS_LANG=AMERICAN_AMERICA.US7ASCII <br />    AMERICAN是语言，AMERICA是地区，US7ASCII是客户端字符集<br /><br />2.5.3客户端字符集设置方法<br />     1)UNIX环境<br />         $NLS_LANG=“simplified chinese”_china.zhs16gbk<br />         $export NLS_LANG<br />         编辑oracle用户的profile文件<br />    2)Windows环境<br />         编辑注册表<br />         Regedit.exe---HKEY_LOCAL_MACHINE---SOFTWARE---ORACLE—HOME0<br /><br />2.5.4 NLS参数查询<br />    Oracle提供若干NLS参数定制数据库和用户机以适应本地格式，例如有NLS_LANGUAGE,NLS_DATE_FORMAT,NLS_CALENDER等，可以通过查询以下数据字典或v$视图查看。<br />    NLS_DATABASE_PARAMETERS--显示数据库当前NLS参数取值，包括数据库字符集取值<br />    NLS_SESSION_PARAMETERS--显示由NLS_LANG 设置的参数，或经过alter session 改变后的参数值（不包括由NLS_LANG 设置的客户端字符集）<br />    NLS_INSTANCE_PARAMETE--显示由参数文件init&lt;SID>.ora 定义的参数V$NLS_PARAMETERS--显示数据库当前NLS参数取值<br /><br />2.5.5修改NLS参数<br />    使用下列方法可以修改NLS参数<br />    （1）修改实例启动时使用的初始化参数文件<br />    （2）修改环境变量NLS_LANG<br />    （3）使用ALTER SESSION语句，在oracle会话中修改<br />    （4）使用某些SQL函数<br />    NLS作用优先级别：Sql function>alter session>环境变量或注册表>参数文件>数据库默认参数<br /><br /> <br /><br />三．导入/导出与字符集转换<br /><br /> <br /><br />3.1 EXP/IMP<br /><br />    Export 和 Import 是一对读写Oracle数据的工具。Export 将 Oracle 数据库中的数据输出到操作系统文件中, Import 把这些文件中的数据读到Oracle 数据库中，由于使用exp/imp进行数据迁移时，数据从源数据库到目标数据库的过程中有四个环节涉及到字符集，如果这四个环节的字符集不一致，将会发生字符集转换。<br /><br />    <br /><br />      EXP                       <br /><br />      IMP                       <br /><br />               <br /><br />    四个字符集是<br />   （1）源数据库字符集<br />   （2）Export过程中用户会话字符集（通过NLS_LANG设定）<br />   （3）Import过程中用户会话字符集（通过NLS_LANG设定）<br />   （4）目标数据库字符集<br /><br /> <br /><br /><br />3.2导出的转换过程<br /><br />    在Export过程中，如果源数据库字符集与Export用户会话字符集不一致，会发生字符集转换，并在导出文件的头部几个字节中存储Export用户会话字符集的ID号。在这个转换过程中可能发生数据的丢失。<br />例:如果源数据库使用ZHS16GBK，而Export用户会话字符集使用US7ASCII，由于ZHS16GBK是16位字符集,而US7ASCII是 7位字符集，这个转换过程中，中文字符在US7ASCII中不能够找到对等的字符，所以所有中文字符都会丢失而变成“?? ”形式，这样转换后生成的Dmp文件已经发生了数据丢失。<br />因此如果想正确导出源数据库数据，则Export过程中用户会话字符集应等于源数据库字符集或是源数据库字符集的超集。<br /><br /> <br /><br />3.3导入的转换过程<br /><br />    （1）确定导出数据库字符集环境<br />    通过读取导出文件头，可以获得导出文件的字符集设置<br />    （2）确定导入session的字符集，即导入Session使用的NLS_LANG环境变量<br />    （3）IMP读取导出文件<br />    读取导出文件字符集ID，和导入进程的NLS_LANG进行比较<br />    （4）如果导出文件字符集和导入Session字符集相同，那么在这一步骤内就不需要转换，如果不同，就需要把数据转换为导入Session使用的字符集。可以看出，导入数据到数据库过程中发生两次字符集转换<br />    第一次:导入文件字符集与导入Session使用的字符集之间的转换，如果这个转换过程不能正确完成，Import向目标数据库的导入过程也就不能完成。<br />    第二次:导入Session字符集与数据库字符集之间的转换。<br />    然而,oracle8i的这种转换只能在单字节字符集之间进行,oracle8i导入Session不支持多字节字符集之间的转换，因此为了避免第一次转换，导入Session使用的NLS_LANG与导出文件字符集相同，第二次转换（通过SQL*Net）支持任何两种字符集。以上情况在Oracle9i 中略有不同。<br /><br /><br />3.4 查询dmp文件的字符集<br /><br />     用Oracle的exp工具导出的dmp文件也包含了字符集信息，dmp文件的第2和第3个字节记录了dmp文件的字符集。如果dmp文件不大，比如只有几M或几十M，可以用UltraEdit打开(16进制方式)，看第2第3个字节的内容，如0354，然后用以下SQL查出它对应的字符集:<br /><br />     SQL> select nls_charset_name(to_number('0354','xxxx')) from dual;<br />     ZHS16GBK<br />    <br />     如果dmp文件很大，比如有2G以上(这也是最常见的情况)，用文本编辑器打开很慢或者完全打不开，可以用以下命令(在unix主机上): <br />     cat exp.dmp |od -x|head -1|awk '{print $2 $3}'|cut -c 3-6  ,然后用上述SQL也可以得到它对应的字符集<br />   <br />3.5 修改dmp文件字符集<br /><br />      dmp文件的第2第3字节记录了字符集信息，因此直接修改dmp文件的第2第3字节的内容就可以‘骗’过oracle的检查。这样做理论上也仅是从子集到超集可以修改，但很多情况下在没有子集和超集关系的情况下也可以修改，我们常用的一些字符集，如 US7ASCII，WE8ISO8859P1，ZHS16CGB231280，ZHS16GBK基本都可以改。因为改的只是dmp文件，所以影响不大。<br /><br />　　具体的修改方法比较多，最简单的就是直接用UltraEdit修改dmp文件的第2和第3个字节。比如想将dmp文件的字符集改为ZHS16GBK，可以用以下SQL查出该种字符集对应的16进制代码:<br /><br />　　SQL> select to_char(nls_charset_id('ZHS16GBK'), 'xxxx') from dual;<br /><br />　　0354<br /><br />　　然后将dmp文件的2、3字节修改为0354即可。<br /><br /><br /><br />四．乱码问题<br /><br /> <br /><br />    oracle在数据存储、迁移过程中经常发生字符乱码问题，归根到底是由于字符集使用不当引起。下面以使用客户端sqlplus向数据库插入数据和导入/导出（EXP/IMP）过程为例，说明乱码产生的原因。<br /><br /> <br /><br />4.1使用客户端sqlplus向数据库存储数据<br /><br />    这个过程存在3个字符集设置<br />    （1）客户端应用字符集<br />    （2）客户端NLS_LANG参数设置<br />    （3）服务器端数据库字符集(Character Set)设置<br />    客户端应用sqlplus中能够显示什么样的字符取决于客户端操作系统语言环境(客户端应用字符集)，但在应用中录入这些字符后，这些字符能否在数据库中正常存储，还与另外两个字符集设置紧密相关，其中客户端NLS_LANG参数主要用于字符数据传输过程中的转换判断。常见的乱码大致有两种情形：<br />    （1）汉字变成问号“？”；<br />当从字符集A 转换成字符集B时，如果转换字符之间不存在对应关系，NLS_LANG使用替代字符“？”替代无法映射的字符<br />    （2）汉字变成未知字符（虽然有些是汉字，但与原字符含义不同）<br />转换存在对应关系，但字符集A 中的字符编码与字符集B 中的字符编码代表不同含义。<br /><br /> <br /><br />4.2发生乱码原因<br /><br />    乱码产生是由于几个字符集之间转换不匹配造成，分以下几种情况：<br />    （注：字符集之间如果不存在子集、超集对应关系时的情况不予考虑，因为这种情况下字符集之间转换必产生乱码）  <br />    1）服务器端数据库字符集与客户端应用字符集相同，与客户端NLS_LANG参数设置不同<br />    如果客户端NLS_LANG字符集是其它两种字符集的子集，转换过程将出现乱码。<br />    解决方法：将三种字符集设置成同一字符集，或NLS_LANG字符集是其它两种字符集的超集<br />    2）服务器端数据库字符集与客户端NLS_LANG参数设置相同，与客户端应用字符集不同<br />    如果客户端应用字符集是其它两种字符集的超集时，转换过程将出现乱码，但对于单字节编码存储中文问题，可参看本文第5章节的分析<br />    3）客户端应用字符集、客户端NLS_LANG参数设置、服务器端数据库字符集互不相同<br />    此种情况较为复杂，但三种字符集之间只要有不能转换的字符，则必产生乱码。<br /><br /> <br /><br />4.3导入/导出过程出现乱码原因<br /><br />    这个过程存在4个字符集设置，在3.1章节中已分析<br />   （1）源数据库字符集<br />   （2）EXP过程中NLS_LANG参数<br />   （3）IMP过程中NLS_LANG参数<br />   （4）目标数据库字符集<br />    出现乱码原因<br />    1）当源数据库字符集不等于EXP过程中NLS_LANG参数，且源数据库字符集是EXP过程中NLS_LANG的子集，才能保证导出文件正确，其他情况则导出文件字符乱码<br />    2）EXP过程中NLS_LANG字符集不等于IMP过程中NLS_LANG字符集，且EXP过程中NLS_LANG字符集是IMP过程中NLS_LANG字符集的子级, 才能保证第一次转换正常，否则第一次转换中出现乱码。<br />    3）如果第一次转换正常，IMP过程中NLS_LANG字符集是目标数据库字符集的子集或相同，才能保证第二次转换正常，否则则第二次转换中出现乱码。<br /><br /> <br /><br />五．单字节编码存储中文问题<br /><br /> <br /><br />    由于历史的原因，早期的oracle没有中文字符集（如oracle6、oracle7、oracle7.1）,但有的用户从那时起就使用数据库了，并用 US7ASCII字符集存储了中文，或是有的用户在创建数据库时，不考虑清楚，随意选择一个默认的字符集，如WE8ISO8859P1或 US7ASCII，而这两个字符集都没有汉字编码，虽然有些时候选用这种字符集好象也能正常使用，但用这种字符集存储汉字信息从原则上说就是错误的，它会给数据库的使用与维护带来一系列的麻烦。<br />    正常情况下，要将汉字存入数据库，数据库字符集必须支持中文，而将数据库字符集设置为US7ASCII等单字节字符集是不合适的。US7ASCII字符集只定义了128个符号，并不支持汉字。另外，如果在SQL*PLUS中能够输入中文，操作系统缺省应该是支持中文的，但如果在NLS_LANG中的字符集设置为US7ASCII，显然也是不正确的，它没有反映客户端的实际情况。但在实际应用中汉字显示却是正确的，这主要是因为Oracle检查数据库与客户端的字符集设置是同样的，那么数据在客户与数据库之间的存取过程中将不发生任何转换，但是这实际上导致了数据库标识的字符集与实际存入的内容是不相符的。而在SELECT的过程中，Oracle同样检查发现数据库与客户端的字符集设置是相同的，所以它也将存入的内容原封不动地传送到客户端，而客户端操作系统识别出这是汉字编码所以能够正确显示。<br />    在这个例子中，数据库与客户端都没有设置成中文字符集，但却能正常显示中文，从应用的角度看好象没问题。然而这里面却存在着极大的隐患，比如在应用length或substr等字符串函数时，就可能得到意外的结果。<br />    对于早期使用US7ASCII字符集数据库的数据迁移到oracle8i/9i中（使用zhs16gbk），由于原始数据已经按照US7ASCII格式存储，对于这种情况，可以通过使用Oracle8i的导出工具，设置导出字符集为US7ASCII，导出后使用UltraEdit等工具打开dmp文件，修改第二、三字符，修改 0001 为0354,这样就可以将US7ASCII字符集的数据正确导入到ZHS16GBK的数据库中。<br /><br /> <br /><br />六．结束语<br /><br />    为了避免在数据库迁移过程中由于字符集不同导致的数据损失，oracle提供了字符集扫描工具（character set scanner），通过这个工具我们可以测试在数据迁移过程中由于字符集转换可能带来的问题，然后根据测试结果，确定数据迁移过程中最佳字符集解决方案。<br /><br /> <br /><br /><br />转至：http://www.fish888.com/
          <br/>
          <span style="color:red;">
            <a href="http://crabboy.javaeye.com/blog/216586#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 19 Jul 2008 22:36:05 +0800</pubDate>
        <link>http://crabboy.javaeye.com/blog/216586</link>
        <guid>http://crabboy.javaeye.com/blog/216586</guid>
      </item>
      <item>
        <title>orale中的动态sql</title>
        <author>crabboy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://crabboy.javaeye.com">crabboy</a>&nbsp;
          链接：<a href="http://crabboy.javaeye.com/blog/216585" style="color:red;">http://crabboy.javaeye.com/blog/216585</a>&nbsp;
          发表时间: 2008年07月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Oracle中的动态SQL<br /><br />        一般的PL/SQL程序设计中，在DML和事务控制的语句中可以直接使用SQL，但是DDL语句及系统控制语句却不能在PL/SQL中直接使用，要想实现在PL/SQL中使用DDL语句及系统控制语句，可以通过使用动态SQL来实现。<br /><br />　　首先我们应该了解什么是动态SQL，在Oracle数据库开发PL/SQL块中我们使用的SQL分为：静态SQL语句和动态SQL语句。所谓静态SQL指在PL/SQL块中使用的SQL语句在编译时是明确的，执行的是确定对象。而动态SQL是指在PL/SQL块编译时SQL语句是不确定的，如根据用户输入的参数的不同而执行不同的操作。编译程序对动态语句部分不进行处理，只是在程序运行时动态地创建语句、对语句进行语法分析并执行该语句。<br /><br />　　Oracle中动态SQL可以通过本地动态SQL来执行，也可以通过DBMS_SQL包来执行。下面就这两种情况分别进行说明：<br /><br />　　一、本地动态SQL<br /><br />　　本地动态SQL是使用EXECUTE IMMEDIATE语句来实现的。<br /><br />　　1、本地动态SQL执行DDL语句：<br /><br />　　需求：根据用户输入的表名及字段名等参数动态建表。<br />create or replace procedure proc_test<br />(<br />    table_name in varchar2,      --表名<br />    field1 in varchar2,          --字段名<br />    datatype1 in varchar2,       --字段类型<br />    field2 in varchar2,          --字段名<br />    datatype2 in varchar2        --字段类型<br />) as <br />    str_sql varchar2(500);<br />begin <br />    str_sql:= 'create table'||' '||table_name||'('||field1||' '||datatype1||','||field2||' '||datatype2||')';<br />    execute immediate str_sql;   --动态执行DDL语句<br />    exception when others then <br />            null;<br />end; <br /><br /> 　　以上是编译通过的存储过程代码。下面执行存储过程动态建表。<br /> SQL> execute proc_test('dinya_test','id','number(8) not null','name','varchar2(100)');<br /><br />       PL/SQL procedure successfully completed<br /><br />  SQL> desc dinya_test;<br />       Name Type          Nullable Default Comments <br />       ---- ------------- -------- ------- --------   <br />       ID   NUMBER(8)<br /><br />       NAME VARCHAR2(100) Y<br /><br />  SQL> <br /><br />  　　到这里，就实现了我们的需求，使用本地动态SQL根据用户输入的表名及字段名、字段类型等参数来实现动态执行DDL语句。<br /><br /> 　　2、本地动态SQL执行DML语句。<br /><br />　　需求：将用户输入的值插入到上例中建好的dinya_test表中。<br />create or replace procedure proc_insert<br />(<br />    id in number,                                 --输入序号<br />    name in varchar2                              --输入姓名<br />) as <br />    str_sql varchar2(500);<br />begin <br />    str_sql:='insert into dinya_test values(:1,:2)';<br />    execute immediate str_sql using id,name;      --动态执行插入操作<br />    exception when others then <br />            null;<br />end; <br /><br />　　执行存储过程，插入数据到测试表中。<br />  SQL> execute proc_insert(1,'dinya');<br />       PL/SQL procedure successfully completed<br />  SQL> select * from dinya_test;<br />        ID      NAME<br />        1       dinya <br /><br />　　在上例中，本地动态SQL执行DML语句时使用了using子句，按顺序将输入的值绑定到变量，如果需要输出参数，可以在执行动态SQL的时候，使用RETURNING INTO 子句，如：<br />declare<br />    p_id number:=1;<br />    v_count number;<br />begin <br />    v_string:='select count(*) from table_name a where a.id=:id';<br />    execute immediate v_string returning into v_count using p_id;  <br />end;<br /><br />    　二、使用DBMS_SQL包<br /><br />　　使用DBMS_SQL包实现动态SQL的步骤如下：<br />    A、先将要执行的SQL语句或一个语句块放到一个字符串变量中。<br />    B、使用DBMS_SQL包的parse过程来分析该字符串。<br />    C、使用DBMS_SQL包的bind_variable过程来绑定变量。<br />    D、使用DBMS_SQL包的execute函数来执行语句。<br /><br />　　1、使用DBMS_SQL包执行DDL语句<br /><br />　　需求：使用DBMS_SQL包根据用户输入的表名、字段名及字段类型建表。<br />create or replace procedure proc_dbms_sql<br />(<br />    table_name in varchar2,       --表名<br />    field_name1 in varchar2,      --字段名<br />    datatype1 in varchar2,        --字段类型<br />    field_name2 in varchar2,      --字段名<br />    datatype2 in varchar2         --字段类型<br />)as<br />    v_cursor number;              --定义光标<br />    v_string varchar2(200);       --定义字符串变量<br />    v_row number;                 --行数<br />begin<br />    v_cursor:=dbms_sql.open_cursor;      --为处理打开光标<br />    v_string:='create table'||' '||table_name||'('||field_name1||' '||datatype1||','||field_name2||' '||datatype2||')';<br />    dbms_sql.parse(v_cursor,v_string,dbms_sql.native);    --分析语句<br />    v_row:=dbms_sql.execute(v_cursor);   --执行语句,动态SQL执行DDL时可以不写<br />    dbms_sql.close_cursor(v_cursor);     --关闭光标<br />    exception when others then<br />            dbms_sql.close_cursor(v_cursor);  --关闭光标<br />            raise;<br />end; <br /><br /> 　　以上过程编译通过后，执行过程创建表结构：<br />SQL> execute proc_dbms_sql('dinya_test2','id','number(8) not null','name','varchar2(100)');<br /><br />           PL/SQL procedure successfully completed<br /><br />SQL> desc dinya_test2;<br />           Name Type          Nullable Default Comments <br />           ---- ------------- -------- ------- -------- <br />           ID   NUMBER(8)                               <br />          NAME VARCHAR2(100) Y                         <br /><br />SQL> <br /><br />  　 2、使用DBMS_SQL包执行DML语句<br /><br />　　需求：使用DBMS_SQL包根据用户输入的值更新表中相对应的记录。<br /><br />　　查看表中已有记录：<br />SQL> select * from dinya_test2;<br />        ID NAME<br />        1 Oracle<br />        2 CSDN<br />        3 ERP<br />SQL> <br /><br /> 　　建存储过程，并编译通过：<br />create or replace procedure proc_dbms_sql_update<br />(<br />    id number,<br />    name varchar2<br />)as<br />    v_cursor number;            --定义光标<br />    v_string varchar2(200);   --字符串变量<br />    v_row number;               --行数<br />begin<br />    v_cursor:=dbms_sql.open_cursor;    --为处理打开光标<br />    v_string:='update dinya_test2 a set a.name=:p_name where a.id=:p_id';<br />    dbms_sql.parse(v_cursor,v_string,dbms_sql.native);     --分析语句<br />    dbms_sql.bind_variable(v_cursor,':p_name',name);       --绑定变量<br />    dbms_sql.bind_variable(v_cursor,':p_id',id);                 --绑定变量<br />    v_row:=dbms_sql.execute(v_cursor);　　　　　       --执行动态SQL<br />    dbms_sql.close_cursor(v_cursor);                                --关闭光标<br />    exception when others then<br />            dbms_sql.close_cursor(v_cursor);                        --关闭光标<br />            raise;<br />end; <br /><br /> 　　执行过程，根据用户输入的参数更新表中的数据：<br />SQL> execute proc_dbms_sql_update(2,'csdn_dinya');<br /><br />        PL/SQL procedure successfully completed<br /><br />SQL> select * from dinya_test2;<br />        ID NAME<br />        1 Oracle<br />        2 csdn_dinya<br />        3 ERP<br />SQL> <br /><br />  　　执行过程后将第二条的name字段的数据更新为新值csdn_dinya。这样就完成了使用dbms_sql包来执行DML语句的功能。<br /><br /> 　　使用DBMS_SQL中，如果要执行的动态语句不是查询语句，使用DBMS_SQL.Execute或 DBMS_SQL.Variable_Value来执行，如果要执行动态语句是查询语句，则要使用DBMS_SQL.define_column定义输出变量，然后使用DBMS_SQL.Execute, DBMS_SQL.Fetch_Rows, DBMS_SQL.Column_Value及DBMS_SQL.Variable_Value来执行查询并得到结果。<br />　　<br />        总结说明：<br /><br />　　在Oracle开发过程中，我们可以使用动态SQL来执行DDL语句、DML语句、事务控制语句及系统控制语句。但是需要注意的是，PL/SQL块中使用动态SQL执行DDL语句的时候与别的不同，在DDL中使用绑定变量是非法的（bind_variable(v_cursor,':p_name',name)），分析后不需要执行DBMS_SQL.Bind_Variable，直接将输入的变量加到字符串中即可。另外，DDL是在调用DBMS_SQL.PARSE时执行的，所以DBMS_SQL.EXECUTE也可以不用，即在上例中的v_row:=dbms_sql.execute(v_cursor)部分可以不要。<br /><br /><br />        转:http://dev.yesky.com/187/2029687.shtml
          <br/>
          <span style="color:red;">
            <a href="http://crabboy.javaeye.com/blog/216585#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 19 Jul 2008 22:35:04 +0800</pubDate>
        <link>http://crabboy.javaeye.com/blog/216585</link>
        <guid>http://crabboy.javaeye.com/blog/216585</guid>
      </item>
      <item>
        <title>jbpm的持久层能使用JPA吗？</title>
        <author>crabboy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://crabboy.javaeye.com">crabboy</a>&nbsp;
          链接：<a href="http://crabboy.javaeye.com/blog/190475" style="color:red;">http://crabboy.javaeye.com/blog/190475</a>&nbsp;
          发表时间: 2008年05月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          大家都知道jbpm的持久层是hibernate，jbpm集成到<br />spring中去 要用sessionFactory。主要代码如下：<pre name="code" class="java">&lt;bean id="sessionFactory"  
          class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
          &lt;property name="dataSource" ref="dataSource" />  
         &lt;property name="configLocations">  
             &lt;list>  
                  &lt;value>classpath:hibernate.cfg.xml&lt;/value>  
             &lt;/list>  
         &lt;/property>  
      &lt;/bean>  </pre><br /><br />而spring框架中使用Jpa 主要是配置：<pre name="code" class="java">&lt;bean name="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		&lt;property name="persistenceXmlLocation"
			value="classpath:persistence.xml" />
		&lt;property name="dataSource" ref="dataSource" />
		&lt;property name="jpaVendorAdapter">
			&lt;bean
				class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
				&lt;property name="database" value="${database.database}" />
				&lt;property name="showSql" value="false" />
				&lt;property name="generateDdl" value="false" />
			&lt;/bean>

		&lt;/property>
		&lt;!--
			&lt;property name="loadTimeWeaver">
			&lt;bean
			class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver" />
			&lt;/property>-->
	&lt;/bean></pre><br /><br />现在：我想既使用JPA ，又要使用JBPM。该如何配置呢？
          <br/>
          <span style="color:red;">
            <a href="http://crabboy.javaeye.com/blog/190475#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 07 May 2008 09:42:41 +0800</pubDate>
        <link>http://crabboy.javaeye.com/blog/190475</link>
        <guid>http://crabboy.javaeye.com/blog/190475</guid>
      </item>
      <item>
        <title>一份完整的Spring+Hibernate+DWR+extJs的生成树及下拉comBoboxTree</title>
        <author>crabboy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://crabboy.javaeye.com">crabboy</a>&nbsp;
          链接：<a href="http://crabboy.javaeye.com/blog/181753" style="color:red;">http://crabboy.javaeye.com/blog/181753</a>&nbsp;
          发表时间: 2008年04月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在各种论坛上看了很久，没见到完整extJs树的生成代码。研究了很久终于实现了Spring+Hibernate+DWR+extJs的生成树及下拉comBoboxTree。<br />     不敢独享收获 ，借javaeye这一平台将我的成果和大家分享。不足和错误之处敬请批评指正。有疑问欢迎联系我。qq：446702119 msn: wh_aq@hotmail.com <br />      <br /><br />     废话少说，还是从生成树开始吧。<br />     一、树的对象模型。<br />         <pre name="code" class="java">
package com.ssgly.model;

import java.util.List;
import java.util.Set;

 
public class Region {
 
	private Long id;
	private String name;
	private String code;
	private Region parent;
	private Set&lt;Region> children = new java.util.HashSet&lt;Region>();

	public Region() {}

	public Region(String name, String code, Region parent) {
		this.name = name;
		this.code = code;
		if(parent!=null) parent.addChild(this);		
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public Region getParent() {
		return parent;
	}

	public void setParent(Region parent) {
		this.parent = parent;
	}

	public Set&lt;Region> getChildren() {
		return children;
	}

	public void setChildren(Set&lt;Region> children) {
		this.children = children;
	}
	 

}
         </pre><br />二、树结构的数据库（mySql）DDL<br /><pre name="code" class="java">
CREATE TABLE `region` (
  `id` bigint(20) NOT NULL,
  `name` varchar(100) default NULL,
  `code` varchar(100) default NULL,
  `parent_id` bigint(20) default NULL,
  PRIMARY KEY  (`id`),
  KEY `FK91AD1314568C1D72` (`parent_id`),
  CONSTRAINT `FK91AD1314568C1D72` FOREIGN KEY (`parent_id`) REFERENCES `region` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
</pre><br />三、对象模型到数据库的Hibernate映射关系<br /><pre name="code" class="java">
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
&lt;hibernate-mapping>
	 
    &lt;class name="com.ssgly.model.Region" table="region"  >
        &lt;id       name="id"   column="id"  type="java.lang.Long">
        	 &lt;generator class="assigned" />
        &lt;/id>        
		&lt;property name="code" column="code" type="java.lang.String" />
	    &lt;property name="name" column="name"  type="java.lang.String"  />
        &lt;many-to-one name="parent"   column="parent_id"    cascade="save-update"  />
        &lt;set name="children"   inverse="true" cascade="save-update"  lazy="false">
        	 &lt;key column="parent_id"  >&lt;/key>
        	 &lt;one-to-many class="com.ssgly.model.Region">&lt;/one-to-many>
        &lt;/set>
    &lt;/class>
&lt;/hibernate-mapping>
</pre><br />四、用Spring框架来管理和支撑持久层、业务逻辑层和展示层<br />【一】持久层采用了DAO模式 。具体设计了一个类型安全的泛型DAO。由于这不是我要讲的重点部分，感兴趣的朋友可以<br />查阅有关文档。要生成一个树，必须要从后台数据库中按一定类型（我用了适配器模式）取出java对象--TreeNode 对象  。及要实现方法 public List&lt;Region> listRegionByParent(Region parent)。<br />TreeNode类型为：<br /><pre name="code" class="java">
 package com.ssgly.model;

 

public  class TreeNode {
	private String id;
	private String Text;
	private boolean leaf;
	private String cls=""; 
	
	private Region region;
	
	public TreeNode(Region region)
	{
			this.region=region;
	}	
	
	public String getId() {		
			return region.getId().toString();
	}
	 
	public boolean getLeaf() {		
			return region.getChildren().size()&lt;1;
	}		
	
	public String getText() {			
			return region.getName();
	}

	public String getCls() {
		return region.getChildren().size()&lt;1?"file":"folder";
	}

  

	 
}
</pre><br /><br />具体生成树的泛型DAO实现是：<br /><pre name="code" class="java">
package com.ssgly.dao;

 

import java.io.IOException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.List;

import com.ssgly.model.Region;

import com.ssgly.model.Page;


public class RegionDAOImpl extends GenericHibernateDAOCrud&lt;Region> implements IRegionDAO {
    
	public RegionDAOImpl(){
		
		super(Region.class);
	}

	public void deleteRegion(Region region) {
		hibernateTemplate.delete(region);
		
	}

	public void deleteRegion(Long id) {
		hibernateTemplate.delete(hibernateTemplate.get(Region.class, id));
		
	}

	public Region getRegion(Long id) {
		 
		return (Region)hibernateTemplate.get(Region.class, id);
	}

	public Long saveRegion(Region region) {
		hibernateTemplate.save(region);
		return region.getId();
	}

	public void updateRegion(Region region) {
		
		hibernateTemplate.saveOrUpdate(region);
	}
	
	/**
	 * 查询父节点的所有子节点
	 * @param parent   父节点
	 * @return  该父节点对应的子节点
	 * 
	 * 
	 **/
	public List&lt;Region> listRegionByParent(Region parent) {
		 if (parent==null){
			 return (List&lt;Region>)hibernateTemplate.find("from Region as r where r.parent is null"); 
		 }else{
			 return (List&lt;Region>)queryForLists("from Region as r where r.parent=?"
		     			 ,new Object[]{parent});
		     
		 }
	    
	}

	
}
</pre><br /><br />从上面java代码中可以看到：DWR需要解析的是 List&lt;Region> 类型的对象。<br />【二】业务逻辑层主要采用一个实现类BusinessServiceImp 。将所有的业务逻辑放在一个类中，一是便于spring中bean好管理，二是方便权限控制。BusinessServiceImp 中的一个很重要的属性是： private IRegionDAO regionDAO; regionDAO的生命周期依赖于spring容器，在spring中管理和维护。逻辑层的代码如下：<br /><pre name="code" class="java">
package com.ssgly.business.impl;

import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.ssgly.model.*;
import com.ssgly.util.Hzxs;

import com.ssgly.business.BusinessService;
import com.ssgly.dao.*;


public class BusinessServiceImpl implements BusinessService {
     
        private IRegionDAO regionDAO;
        
        public void setRegionDAO(IRegionDAO regionDAO) {
			this.regionDAO = regionDAO;
		}
	 
		public List&lt;TreeNode> getAllChildren(Long parentId) throws IOException,
				SQLException {
			List&lt;Region> listRegion=regionDAO.listRegionByParent(regionDAO.getRegion(parentId));
			List&lt;TreeNode> listTreeNode=new ArrayList&lt;TreeNode>();
			for(Region region:listRegion){
				System.out.println(">>"+region.getName());
				listTreeNode.add(new TreeNode(region));
			}
			//System.out.println("List&lt;TreeNode> getAllChildren 方法已执行!");
			return listTreeNode;
		}
		 
		
}
</pre><br />【三】Spring容器的配置主要是通过xml方式体现。<br />一是：web.xml的配置如下：<br /><pre name="code" class="java">
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
&lt;web-app>
   &lt;context-param>
        &lt;param-name>contextConfigLocation&lt;/param-name>
        &lt;param-value>
            /WEB-INF/dispatcherServlet-servlet.xml,
            /WEB-INF/model-config.xml            
        &lt;/param-value>
    &lt;/context-param>
  &lt;!-- log4j config -->
    &lt;context-param>
        &lt;param-name>log4jConfigLocation&lt;/param-name>
        &lt;param-value>/WEB-INF/log4j.properties&lt;/param-value>
    &lt;/context-param>   
 &lt;!--========================================================================
        Filters
    =========================================================================-->

    &lt;filter>
        &lt;filter-name>encodingFilter&lt;/filter-name>
        &lt;filter-class>com.ssgly.web.filter.EncodingFilter&lt;/filter-class>
        &lt;init-param>
            &lt;param-name>encoding&lt;/param-name>
            &lt;param-value>utf-8&lt;/param-value>
        &lt;/init-param>
    &lt;/filter>
    &lt;filter-mapping>
        &lt;filter-name>encodingFilter&lt;/filter-name>
        &lt;url-pattern>*&lt;/url-pattern>
    &lt;/filter-mapping>    
 &lt;!--========================================================================
        Listeners
    =========================================================================-->

    &lt;listener>
        &lt;listener-class>
            org.springframework.web.util.Log4jConfigListener
        &lt;/listener-class>
    &lt;/listener>
    &lt;listener>
        &lt;listener-class>
            org.springframework.web.context.ContextLoaderListener
        &lt;/listener-class>
    &lt;/listener>
   
  &lt;!--========================================================================
        Servlets
    =========================================================================-->
    &lt;servlet>
        &lt;servlet-name>dispatcherServlet&lt;/servlet-name>
        &lt;servlet-class>org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class>
        &lt;load-on-startup>0&lt;/load-on-startup>
    &lt;/servlet>

    &lt;servlet-mapping>
        &lt;servlet-name>dispatcherServlet&lt;/servlet-name>
        &lt;url-pattern>*.do&lt;/url-pattern>
    &lt;/servlet-mapping>
&lt;!--========================================================================
        DWR 配置
    =========================================================================-->
	&lt;!--配置DWR拦截器-->   
	 &lt;servlet>   
		  &lt;servlet-name>dwr-invoker&lt;/servlet-name>   
		  &lt;servlet-class>org.directwebremoting.servlet.DwrServlet&lt;/servlet-class>   
		  &lt;init-param>   
		   &lt;param-name>debug&lt;/param-name>   
		   &lt;param-value>true&lt;/param-value>   
		  &lt;/init-param>
		  &lt;init-param>
	        &lt;param-name>classes&lt;/param-name>
	        &lt;param-value>java.lang.Object&lt;/param-value>
	      &lt;/init-param>
	      &lt;load-on-startup>100&lt;/load-on-startup>
	 &lt;/servlet>   
	 &lt;servlet-mapping>   
	  &lt;servlet-name>dwr-invoker&lt;/servlet-name>   
	  &lt;url-pattern>/dwr/*&lt;/url-pattern>   
	 &lt;/servlet-mapping>
 &lt;!--========================================================================
        Session
    =========================================================================-->

    &lt;session-config>
        &lt;session-timeout>30&lt;/session-timeout>
    &lt;/session-config>

     
 
 
&lt;/web-app>


</pre><br />二是：bean生成的配置。model-config.xml<br /><pre name="code" class="java">
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" 
 "http://www.springframework.org/dtd/spring-beans.dtd"> 
 &lt;beans>
     
     &lt;bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        &lt;property name="locations">
            &lt;list>
                &lt;value>/WEB-INF/jdbc.properties&lt;/value>                
            &lt;/list>
        &lt;/property>
    &lt;/bean>
     
   &lt;bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        &lt;property name="driverClassName" value="${jdbc.driver}" />
        &lt;property name="url" value="${jdbc.url}" />
        &lt;property name="username" value="${jdbc.username}" />
        &lt;property name="password" value="${jdbc.password}" />
    &lt;/bean>    


    &lt;bean id="sessionFactory"
                 class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"  destroy-method="close">
            &lt;property name="dataSource">
                 &lt;ref local="myDataSource" />
            &lt;/property>
            &lt;property name="mappingResources">
                &lt;list>
                   &lt;value> com/ssgly/model/Region.hbm.xml&lt;/value>                
			    &lt;/list>
            &lt;/property>
            &lt;property name="hibernateProperties">
              &lt;props>
              	&lt;prop key="connection.characterEncoding">utf-8&lt;/prop>
                &lt;prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect&lt;/prop>
                &lt;prop key="hibernate.jdbc.batch_size">50&lt;/prop> 
                &lt;prop key="hibernate.show_sql">true&lt;/prop>
                &lt;prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory&lt;/prop>
                &lt;/props>
            &lt;/property>
        &lt;/bean>
  
    &lt;bean id="transactionManager" 
          class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
        &lt;property name="sessionFactory"> 
            &lt;ref bean="sessionFactory"/> 
        &lt;/property> 
    &lt;/bean>
    
    &lt;bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
	     &lt;property name="sessionFactory"> &lt;ref bean="sessionFactory"/> &lt;/property>
    &lt;/bean>
    
 
     &lt;bean id="regionDao"  class="com.ssgly.dao.RegionDAOImpl">
        &lt;property name="hibernateTemplate"> 
            &lt;ref bean="hibernateTemplate"/>
        &lt;/property>            
     &lt;/bean>									 
   &lt;bean id="businessService" class="com.ssgly.business.impl.BusinessServiceImpl">
   	   &lt;property name="regionDAO">&lt;ref  bean="regionDao" />&lt;/property>
   	   
   &lt;/bean>
   
   &lt;bean id="todoSsglyService"  class="com.ssgly.ext.ToDoImpl">
        &lt;property name="businessServiceImpl"> 
            &lt;ref bean="businessService"/>
        &lt;/property>            
   &lt;/bean>
   
   
&lt;/beans>
</pre><br />三是：servlet配置 dispatcherServlet-servlet.xml<br /><pre name="code" class="java">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" 
 "http://www.springframework.org/dtd/spring-beans.dtd"> 

&lt;beans>
    &lt;!--============================================================================
        URL Mapping configuration
    =============================================================================-->

    &lt;bean id="beanNameUrlMapping"
        class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
        &lt;property name="alwaysUseFullPath" value="true" />
    &lt;/bean>
   &lt;!--============================================================================
        Velocity configuration
    =============================================================================-->

    &lt;bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
        &lt;property name="contentType">&lt;value>text/html;charset=GBK&lt;/value>&lt;/property>
    &lt;/bean>

    &lt;bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        &lt;property name="configLocation" value="/WEB-INF/velocity.properties" />
        &lt;property name="resourceLoaderPath" value="/" />
    &lt;/bean>
 
    &lt;bean id="treeRegionServlet"  name="/treeRegionServlet.do" class="com.ssgly.web.TreeRegionServlet">
        &lt;property name="businessService">
            &lt;ref bean="businessService"/>
        &lt;/property>
    &lt;/bean>
&lt;/beans>
</pre><br />    有了这些xml的配置。Spring能将三层很好地组合起来。以上是java部分。还没有讲到extJs。extJs可以接受asp、php、java等服务器端生成的json格式的对象。就java来说 ，extJs能接受三种方式的json对象，一是servlet中拼接json对象；其次是引用json lib 包；三是DWR方式，绕过Controller（就Spring来说）或servlet，在javascript中 直接调用java业务逻辑层中的方法（通过DWR引擎），利用dwr代理或者javascript 回调函数返回json对象并在页面展示。<br />    本人采用了第三种DWR方式实现ExtJs生成树。要使用dwr 就的要在以上几个配置文件中配置DWR（已配）。具体的下次再说吧。<br />    今天就写到这里吧。不知写的怎么样？有朋友关注这一块？若支持，请鼓励一下；写的不好、不对或不懂的地方，请拍砖。（续）<br /><br />    抱歉啊，这几天忙着考驾照，把这事给耽搁啊。书接上回吧。<br />【四】基于Spring方式的DWR配置说明。 <br /> 一、首先在WEB.xml中配置dwr拦截器 代码如下（节选）：<br /><pre name="code" class="java">
&lt;!--配置DWR拦截器-->   
	 &lt;servlet>   
             &lt;servlet-name>dwr-invoker&lt;/servlet-name>   
	  &lt;servlet-class>org.directwebremoting.servlet.DwrServlet&lt;/servlet-class>   
		  &lt;init-param>   
		   &lt;param-name>debug&lt;/param-name>   
		   &lt;param-value>false&lt;/param-value>   
		  &lt;/init-param>
		  &lt;init-param>
	        &lt;param-name>classes&lt;/param-name>
	        &lt;param-value>java.lang.Object&lt;/param-value>
	      &lt;/init-param>
	      &lt;load-on-startup>100&lt;/load-on-startup>
	 &lt;/servlet>   
	 &lt;servlet-mapping>   
	  &lt;servlet-name>dwr-invoker&lt;/servlet-name>   
	  &lt;url-pattern>/dwr/*&lt;/url-pattern>   
	 &lt;/servlet-mapping>
</pre><br />二、dwr.xml的配置。这里将Spring管理的bean映射成javascipt操作的对象。更直观的说法就是使得页面中javascript能直接使用java中对象的方法。代码如下:<br /><pre name="code" class="java">
 &lt;?xml version="1.0" encoding="utf-8"?>
&lt;!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
	"http://getahead.ltd.uk/dwr/dwr20.dtd">

&lt;dwr>
    &lt;allow>
    	&lt;convert converter="bean"  match="com.ssgly.model.*"/>
    	&lt;convert converter="map" match="org.directwebremoting.convert.MapConverter"/> 
    	&lt;create creator="spring" javascript="treeBusinessService">
    	  &lt;param name="beanName" value="businessService"/>
		  &lt;include method="getAllChildren" />
		&lt;/create>
	&lt;/allow>
  
&lt;/dwr>
</pre><br /><br />    从上面的代码可以看出，javascript使用treeBusinessService.getAllChildren 方法就能够直接取出 Spring维持的业务逻辑层定义的bean----- businessService。从而完成了DWR的功能。这里当然存在安全问题，在这里暂时没有讨论，关于如何在DWR中进行安全控制，大家可以参考有关文档。本文暂不考虑。<br />【五】ext和服务器端交互的机制和具体实现<br />    一般说来，按照上面DWR的配置，就已经实现了在页面中使用java的方法。但java方法执行后生成的List 传回到页面还需要靠回调函数实现。例如下面代码就是包含了回调函数的测试页。<br /><pre name="code" class="java">
&lt;html>
&lt;head>      
    &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8">   
&lt;title>ExtJS－树示例&lt;/title>
&lt;link rel="stylesheet" type="text/css" href="ext2/resources/css/ext-all.css" />
&lt;script type="text/javascript" src="ext2/adapter/ext/ext-base.js">&lt;/script>
&lt;script type="text/javascript" src="ext2/ext-all.js">&lt;/script>
 
<pre name="code" class="java">&lt;script type="text/javascript" src="dwr/interface/treeBusinessService.js ">&lt;/script>
&lt;script type="text/javascript" src="dwr/engine.js ">&lt;/script>
&lt;script type="text/javascript" src="dwr/util.js ">&lt;/script></pre> <br />&lt;script type="text/javascript"><br />	 	<br />	treeBusinessService.getAllChildren(1,function(ret){<br />	                                 alert("一共有"+ret.length+"个子节点");<br />	                               });<br /><br />&lt;/script><br />&lt;/head><br />	<br />&lt;body><br />&lt;div id="tree-div">&lt;/div>     <br />&lt;/body><br />&lt;/html><br /></pre><br /><br />现在分析一下上面页面主要代码：<br /><br /><pre name="code" class="java">
&lt;script type="text/javascript" src="dwr/interface/treeBusinessService.js ">&lt;/script>
 
</pre><br />这句中的treeBusinessService就是DWR.xml中定义的<pre name="code" class="java">&lt;create creator="spring" javascript="treeBusinessService"></pre><br /><br />下面两句是使用DWR所必需的，原样加上即可。<br /><pre name="code" class="java">
 &lt;script type="text/javascript" src="dwr/engine.js ">&lt;/script>
 &lt;script type="text/javascript" src="dwr/util.js ">&lt;/script>
</pre><br />有了上面的这些DWR配置，就能够以DWR的方式使用java的方法啦：<br /><pre name="code" class="java">
&lt;script type="text/javascript">
	 	
	treeBusinessService.getAllChildren(1,function(ret){
	                                 alert("一共有"+ret.length+"个子节点");
	                               });

&lt;/script>

</pre><br />   function(ret)就是回调函数。因为treeBusinessService.getAllChildren执行的结果是List类型，DWR解析List到页面应该是javascript的对象数组，所以ret应该是个数组，ret.length是这个数组的长度。<br /><br />   上面的例子只不过是原理性的介绍，帮助我们理解javascript如何和后台进行的交互。真正要实现DWRTree 还需要专门的DWRTreeLoader代理。下面这段代码很是重要，参考了ext官方bbs上的代码，并做了修改。先提供如下：<br /><pre name="code" class="java">
Ext.tree.DWRTreeLoader = function(config) {
  Ext.tree.DWRTreeLoader.superclass.constructor.call(this, config);
};

Ext.extend(Ext.tree.DWRTreeLoader, Ext.tree.TreeLoader, {
   args:[],
   requestData : function(node, callback) {
    if (this.fireEvent("beforeload", this, node, callback) !== false) {

     
      var callParams = new Array();
      var success = this.handleResponse.createDelegate(this, [node, callback], 1);
      var error = this.handleFailure.createDelegate(this, [node, callback], 1);
      callParams.push(node.id);
      callParams.push({callback:success, errorHandler:error});

      //todo: do we need to set this to something else?
      this.transId=true;
      this.dataUrl.apply(this, callParams);
    } else {
      // if the load is cancelled, make sure we notify
      // the node that we are done
      if (typeof callback == "function") {
        //alert(callback);
        callback();
      }
    }
  },
    processResponse : function(response, node, callback){
        try {
          for(var i = 0; i &lt; response.length; i++){
                var n = this.createNode(response[i]);
                if(n){
                    node.appendChild(n);
                }
            }
            if(typeof callback == "function"){
                callback(this, node);
            }
        }catch(e){
            this.handleFailure(response);
        }
    },

    handleResponse : function(response, node, callback){
        this.transId = false;
        this.processResponse(response, node, callback);
        this.fireEvent("load", this, node, response);
    },

    handleFailure : function(response, node, callback){
        this.transId = false;
        this.fireEvent("loadexception", this, node, response);
        if(typeof callback == "function"){
            callback(this, node);
        }
    }

});  

</pre><br /><br />上面的代码可以直接在项目中使用，无需修改。<br />【六】最终DWRTree的实现包括 tree.js和 tree.html<br />tree.js完整代码如下：<br /><pre name="code" class="java">
 Ext.onReady(function(){ 
  
Ext.tree.DWRTreeLoader = function(config) {
  Ext.tree.DWRTreeLoader.superclass.constructor.call(this, config);
};

Ext.extend(Ext.tree.DWRTreeLoader, Ext.tree.TreeLoader, {
   args:[],
   requestData : function(node, callback) {
    if (this.fireEvent("beforeload", this, node, callback) !== false) {

     
      var callParams = new Array();
      var success = this.handleResponse.createDelegate(this, [node, callback], 1);
      var error = this.handleFailure.createDelegate(this, [node, callback], 1);
      callParams.push(node.id);
      callParams.push({callback:success, errorHandler:error});

      //todo: do we need to set this to something else?
      this.transId=true;
      this.dataUrl.apply(this, callParams);
    } else {
      // if the load is cancelled, make sure we notify
      // the node that we are done
      if (typeof callback == "function") {
        //alert(callback);
        callback();
      }
    }
  },
    processResponse : function(response, node, callback){
        try {
          for(var i = 0; i &lt; response.length; i++){
                var n = this.createNode(response[i]);
                if(n){
                    node.appendChild(n);
                }
            }
            if(typeof callback == "function"){
                callback(this, node);
            }
        }catch(e){
            this.handleFailure(response);
        }
    },

    handleResponse : function(response, node, callback){
        this.transId = false;
        this.processResponse(response, node, callback);
        this.fireEvent("load", this, node, response);
    },

    handleFailure : function(response, node, callback){
        this.transId = false;
        this.fireEvent("loadexception", this, node, response);
        if(typeof callback == "function"){
            callback(this, node);
        }
    }

});  


var myTree = new Ext.tree.TreePanel({   
    	el:Ext.getBody(),  
        autoScroll:true,
        animate:true,
        width:'300px',
        height:'800px',
        enableDD:true,
        containerScroll: true, 
		root:new Ext.tree.AsyncTreeNode({
             text: '单位',
             draggable:false,
             id:'1' }),
        loader:new Ext.tree.DWRTreeLoader({ 
	               dataUrl:treeBusinessService.getAllChildren, 
			       listeners : {
			                  'beforeload' : function( node) {
				                   myTree.getLoader().args[0]=(node.id!='root'?node.id:"1");
			                    }
		           }
			   })
    });
	
	myTree.render();


    
});
</pre><br />提个醒：这句<pre name="code" class="java"> myTree.getLoader().args[0]=(node.id!='root'?node.id:"1");
</pre>不能错哦，它是和 DWRTreeLoader耦合的。<br /><br />tree.html是这样的：<br /><pre name="code" class="java">
&lt;html>
&lt;head>      
    &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8">   
&lt;title>ExtJS－树示例&lt;/title>
&lt;link rel="stylesheet" type="text/css" href="ext2/resources/css/ext-all.css" />
&lt;script type="text/javascript" src="ext2/adapter/ext/ext-base.js">&lt;/script>
&lt;script type="text/javascript" src="ext2/ext-all.js">&lt;/script>
 
&lt;script type="text/javascript" src="dwr/interface/treeBusinessService.js ">&lt;/script>
&lt;script type="text/javascript" src="dwr/engine.js ">&lt;/script>
&lt;script type="text/javascript" src="dwr/util.js ">&lt;/script>
&lt;script type="text/javascript" src="js/tree.js">&lt;/script> 
  
&lt;/head>
	
&lt;body>
 
&lt;/body>
&lt;/html>
</pre><br /><br />  好了，基于Spring+hibernate+dwr+EXTJs的DWRTreeLoader的实现就是这样。本想提供完整代码下载。但想来想去还是让读者自己结合我的文章边做边体会比较好。说不定还能优化我的代码呢。你说是吗？<br /><br />  还有comBoboxTree的实现没有写。也不知大家感兴趣没？还是欢迎大家多提意见吧。
          <br/>
          <span style="color:red;">
            <a href="http://crabboy.javaeye.com/blog/181753#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 11 Apr 2008 14:06:44 +0800</pubDate>
        <link>http://crabboy.javaeye.com/blog/181753</link>
        <guid>http://crabboy.javaeye.com/blog/181753</guid>
      </item>
      <item>
        <title>完整的Spring+Hibernate+DWR+extJs的生成树及下拉comBoboxTree</title>
        <author>crabboy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://crabboy.javaeye.com">crabboy</a>&nbsp;
          链接：<a href="http://crabboy.javaeye.com/blog/170186" style="color:red;">http://crabboy.javaeye.com/blog/170186</a>&nbsp;
          发表时间: 2008年03月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div class="quote_title">wxc2100 写道</div><div class="quote_div">谢谢楼主回复！本人初学，还有一个问题呀：<br /> public class RegionDAOImpl extends GenericHibernateDAOCrud&lt;Region> implements IRegionDAO {  <br />中的GenericHibernateDAOCrud在那里呀！谢谢了！</div><br /><br /><br />GenericHibernateDAOCrud 这个类可以提供给你。它在DAO层对Hibernate增、删、改、查的基类支持。也就是我文章中提到的DAO模式。<br /><pre name="code" class="java">

package com.ssgly.dao;

 
import java.io.Serializable;
import java.lang.reflect.Field;
import java.sql.SQLException;
import java.util.*;

import com.ssgly.model.*;

import org.apache.commons.logging.*;
import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

/**
 * This base class is prepared for subclass to do CRUD easily.
 * 
 * @author Tiger
 */
public abstract class GenericHibernateDAOCrud&lt;T> {

    protected static final Object[] EMPTY_OBJECT_ARRAY = new Object[] {};

    protected Log log = LogFactory.getLog(getClass());

    private final Class&lt;T> clazz;
    protected HibernateTemplate hibernateTemplate;

    /**
     * Inject domain's class type in constructor.
     * 
     * @param clazz Domain's class.
     */
    public GenericHibernateDAOCrud(Class&lt;T> clazz) {
        this.clazz = clazz;
    }

    /**
     * @spring.property name="hibernateTemplate" ref="hibernateTemplate"
     */
    public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
        this.hibernateTemplate = hibernateTemplate;
    }

    @SuppressWarnings("unchecked")
    public T query(Serializable id) {
        T t = (T)hibernateTemplate.get(clazz, id);
        if(t==null)
            throw new DataRetrievalFailureException("Object not found.");
        // it is strange that load() method return a lazy-loading proxy object 
        // and it may cause LazyInitializationException!
        return t;
    }

    /**
     * Default implementation of creating new domain object.
     */
    public void create(T t) {
        hibernateTemplate.save(t);
    }

    /**
     * Default implementation of deleting new domain object.
     */
    public void delete(T t) {
        hibernateTemplate.delete(t);
    }

    /**
     * Default implementation of updating domain object.
     */
    public void update(T t) {
        hibernateTemplate.update(t);
    }

    /**
     * Do an update hql query, return the affected rows.
     * 
     * @param updateHql Update HQL.
     * @param values Parameters or null if none.
     * @return The affected rows.
     */
    protected int executeUpdate(final String updateHql, final Object[] values) {
        HibernateCallback updateCallback = new HibernateCallback() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query query = session.createQuery(updateHql);
                if(values!=null) {
                    for(int i=0; i&lt;values.length; i++)
                        query.setParameter(i, values[i]);
                }
                return new Integer(query.executeUpdate());
            }
        };
        return ((Integer)hibernateTemplate.execute(updateCallback)).intValue();
    }

    /**
     * Prepared for sub-class for convenience. Query for list and also return 
     * total results' number.
     * 
     * @param selectCount HQL for "select count(*) from ..." and should return a Long.
     * @param select HQL for "select * from ..." and should return object list.
     * @param values For prepared statements.
     * @param page Page object for store page information.
     */
    protected List queryForList(final String selectCount, final String select, final Object[] values, final Page page) {
        Long count = (Long)queryForObject(selectCount, values);
        page.setTotalCount(count.intValue());
        if(page.isEmpty())
            return Collections.EMPTY_LIST;
        return queryForList(select, values, page);
    }

    /**
     * Prepared for sub-class for convenience. Query for list but do not return 
     * total results' number.
     * 
     * @param select HQL for "select * from ..." and should return object list.
     * @param values For prepared statements.
     * @param page Page object for store page information.
     */
    protected List queryForList(final String select, final Object[] values, final Page page) {
        // select:
        HibernateCallback selectCallback = new HibernateCallback() {
            public Object doInHibernate(Session session) {
                Query query = session.createQuery(select);
                if(values!=null) {
                    for(int i=0; i&lt;values.length; i++)
                        query.setParameter(i, values[i]);
                }
                return query.setFirstResult(page.getFirstResult())
                            .setMaxResults(page.getPageSize())
                            .list();
            }
        };
        return (List) hibernateTemplate.executeFind(selectCallback);
    }

    /**
     * Prepared for sub-class for convenience. Query for unique result.
     * 
     * @param select HQL for "select * from ..." and should return unique object.
     * @param values For prepared statements.
     */
    protected Object queryForObject(final String select, final Object[] values) {
        HibernateCallback selectCallback = new HibernateCallback() {
            public Object doInHibernate(Session session) {
                Query query = session.createQuery(select);
                if(values!=null) {
                    for(int i=0; i&lt;values.length; i++)
                        query.setParameter(i, values[i]);
                }
                return query.uniqueResult();
            }
        };
        return hibernateTemplate.execute(selectCallback);
    }

    protected Object queryForObject(final DetachedCriteria dc) {
        HibernateCallback callback = new HibernateCallback() {
            public Object doInHibernate(Session session) {
                return dc.getExecutableCriteria(session).uniqueResult();
            }
        };
        return hibernateTemplate.execute(callback);
    }

    

    /**
     * Prepared for sub-class for convenience.
     */
    protected Object uniqueResult(final DetachedCriteria dc) {
        HibernateCallback callback = new HibernateCallback() {
            public Object doInHibernate(Session session) {
                return dc.getExecutableCriteria(session).uniqueResult();
            }
        };
        return hibernateTemplate.execute(callback);
    }
    protected List queryForLists(final String select, final Object[] values) {
        // select:
        HibernateCallback selectCallback = new HibernateCallback() {
            public Object doInHibernate(Session session) {
                Query query = session.createQuery(select);
                if(values!=null) {
                    for(int i=0; i&lt;values.length; i++)
                        query.setParameter(i, values[i]);
                }
                return query.list();
            }
        };
        return (List) hibernateTemplate.executeFind(selectCallback);
    }

}



</pre>
          <br/>
          <span style="color:red;">
            <a href="http://crabboy.javaeye.com/blog/170186#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 11 Mar 2008 14:33:12 +0800</pubDate>
        <link>http://crabboy.javaeye.com/blog/170186</link>
        <guid>http://crabboy.javaeye.com/blog/170186</guid>
      </item>
      <item>
        <title>缓存设计</title>
        <author>crabboy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://crabboy.javaeye.com">crabboy</a>&nbsp;
          链接：<a href="http://crabboy.javaeye.com/blog/164631" style="color:red;">http://crabboy.javaeye.com/blog/164631</a>&nbsp;
          发表时间: 2008年02月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://dev2dev.bea.com.cn/techdoc/2007/07/java-soa-ReadWriteLock.html" target="_blank">http://dev2dev.bea.com.cn/techdoc/2007/07/java-soa-ReadWriteLock.html</a>
          <br/>
          <span style="color:red;">
            <a href="http://crabboy.javaeye.com/blog/164631#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 24 Feb 2008 21:00:32 +0800</pubDate>
        <link>http://crabboy.javaeye.com/blog/164631</link>
        <guid>http://crabboy.javaeye.com/blog/164631</guid>
      </item>
      <item>
        <title>一份完整的Spring+Hibernate+DWR+extJs的生成树及下拉comBoboxTree</title>
        <author>crabboy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://crabboy.javaeye.com">crabboy</a>&nbsp;
          链接：<a href="http://crabboy.javaeye.com/blog/162551" style="color:red;">http://crabboy.javaeye.com/blog/162551</a>&nbsp;
          发表时间: 2008年02月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在各种论坛上看了很久，没见到完整extJs树的生成代码。研究了很久终于实现了Spring+Hibernate+DWR+extJs的生成树及下拉comBoboxTree。<br />     不敢独享收获 ，借javaeye这一平台将我的成果和大家分享。不足和错误之处敬请批评指正。有疑问欢迎联系我。qq：446702119 msn: wh_aq@hotmail.com <br />     在此要感谢javaeye、感谢ext官方论坛和大峡 ，感谢CCTV、CHANNEL V 。。。。。呵呵。<br /><br />     废话少说，还是从生成树开始吧。<br />     一、树的对象模型。<br />         <pre name="code" class="java">
package com.ssgly.model;

import java.util.List;
import java.util.Set;

 
public class Region {
 
	private Long id;
	private String name;
	private String code;
	private Region parent;
	private Set&lt;Region> children = new java.util.HashSet&lt;Region>();

	public Region() {}

	public Region(String name, String code, Region parent) {
		this.name = name;
		this.code = code;
		if(parent!=null) parent.addChild(this);		
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public Region getParent() {
		return parent;
	}

	public void setParent(Region parent) {
		this.parent = parent;
	}

	public Set&lt;Region> getChildren() {
		return children;
	}

	public void setChildren(Set&lt;Region> children) {
		this.children = children;
	}
	 

}
         </pre><br />二、树结构的数据库（mySql）DDL<br /><pre name="code" class="java">
CREATE TABLE `region` (
  `id` bigint(20) NOT NULL,
  `name` varchar(100) default NULL,
  `code` varchar(100) default NULL,
  `parent_id` bigint(20) default NULL,
  PRIMARY KEY  (`id`),
  KEY `FK91AD1314568C1D72` (`parent_id`),
  CONSTRAINT `FK91AD1314568C1D72` FOREIGN KEY (`parent_id`) REFERENCES `region` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
</pre><br />三、对象模型到数据库的Hibernate映射关系<br /><pre name="code" class="java">
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
&lt;hibernate-mapping>
	 
    &lt;class name="com.ssgly.model.Region" table="region"  >
        &lt;id       name="id"   column="id"  type="java.lang.Long">
        	 &lt;generator class="assigned" />
        &lt;/id>        
		&lt;property name="code" column="code" type="java.lang.String" />
	    &lt;property name="name" column="name"  type="java.lang.String"  />
        &lt;many-to-one name="parent"   column="parent_id"    cascade="save-update"  />
        &lt;set name="children"   inverse="true" cascade="save-update"  lazy="false">
        	 &lt;key column="parent_id"  >&lt;/key>
        	 &lt;one-to-many class="com.ssgly.model.Region">&lt;/one-to-many>
        &lt;/set>
    &lt;/class>
&lt;/hibernate-mapping>
</pre><br />四、用Spring框架来管理和支撑持久层、业务逻辑层和展示层<br />【一】持久层采用了DAO模式 。具体设计了一个类型安全的泛型DAO。由于这不是我要讲的重点部分，感兴趣的朋友可以<br />查阅有关文档。要生成一个树，必须要从后台数据库中按一定类型（我用了适配器模式）取出java对象--TreeNode 对象  。及要实现方法 public List&lt;Region> listRegionByParent(Region parent)。<br />TreeNode类型为：<br /><pre name="code" class="java">
 package com.ssgly.model;

 

public  class TreeNode {
	private String id;
	private String Text;
	private boolean leaf;
	private String cls=""; 
	
	private Region region;
	
	public TreeNode(Region region)
	{
			this.region=region;
	}	
	
	public String getId() {		
			return region.getId().toString();
	}
	 
	public boolean getLeaf() {		
			return region.getChildren().size()&lt;1;
	}		
	
	public String getText() {			
			return region.getName();
	}

	public String getCls() {
		return region.getChildren().size()&lt;1?"file":"folder";
	}

  

	 
}
</pre><br /><br />具体生成树的泛型DAO实现是：<br /><pre name="code" class="java">
package com.ssgly.dao;

 

import java.io.IOException;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.List;

import com.ssgly.model.Region;

import com.ssgly.model.Page;


public class RegionDAOImpl extends GenericHibernateDAOCrud&lt;Region> implements IRegionDAO {
    
	public RegionDAOImpl(){
		
		super(Region.class);
	}

	public void deleteRegion(Region region) {
		hibernateTemplate.delete(region);
		
	}

	public void deleteRegion(Long id) {
		hibernateTemplate.delete(hibernateTemplate.get(Region.class, id));
		
	}

	public Region getRegion(Long id) {
		 
		return (Region)hibernateTemplate.get(Region.class, id);
	}

	public Long saveRegion(Region region) {
		hibernateTemplate.save(region);
		return region.getId();
	}

	public void updateRegion(Region region) {
		
		hibernateTemplate.saveOrUpdate(region);
	}
	
	/**
	 * 查询父节点的所有子节点
	 * @param parent   父节点
	 * @return  该父节点对应的子节点
	 * 
	 * 
	 **/
	public List&lt;Region> listRegionByParent(Region parent) {
		 if (parent==null){
			 return (List&lt;Region>)hibernateTemplate.find("from Region as r where r.parent is null"); 
		 }else{
			 return (List&lt;Region>)queryForLists("from Region as r where r.parent=?"
		     			 ,new Object[]{parent});
		     
		 }
	    
	}

	
}
</pre><br /><br />从上面java代码中可以看到：DWR需要解析的是 List&lt;Region> 类型的对象。<br />【二】业务逻辑层主要采用一个实现类BusinessServiceImp 。将所有的业务逻辑放在一个类中，一是便于spring中bean好管理，二是方便权限控制。BusinessServiceImp 中的一个很重要的属性是： private IRegionDAO regionDAO; regionDAO的生命周期依赖于spring容器，在spring中管理和维护。逻辑层的代码如下：<br /><pre name="code" class="java">
package com.ssgly.business.impl;

import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.ssgly.model.*;
import com.ssgly.util.Hzxs;

import com.ssgly.business.BusinessService;
import com.ssgly.dao.*;


public class BusinessServiceImpl implements BusinessService {
     
        private IRegionDAO regionDAO;
        
        public void setRegionDAO(IRegionDAO regionDAO) {
			this.regionDAO = regionDAO;
		}
	 
		public List&lt;TreeNode> getAllChildren(Long parentId) throws IOException,
				SQLException {
			List&lt;Region> listRegion=regionDAO.listRegionByParent(regionDAO.getRegion(parentId));
			List&lt;TreeNode> listTreeNode=new ArrayList&lt;TreeNode>();
			for(Region region:listRegion){
				System.out.println(">>"+region.getName());
				listTreeNode.add(new TreeNode(region));
			}
			//System.out.println("List&lt;TreeNode> getAllChildren 方法已执行!");
			return listTreeNode;
		}
		 
		
}
</pre><br />【三】Spring容器的配置主要是通过xml方式体现。<br />一是：web.xml的配置如下：<br /><pre name="code" class="java">
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
&lt;web-app>
   &lt;context-param>
        &lt;param-name>contextConfigLocation&lt;/param-name>
        &lt;param-value>
            /WEB-INF/dispatcherServlet-servlet.xml,
            /WEB-INF/model-config.xml            
        &lt;/param-value>
    &lt;/context-param>
  &lt;!-- log4j config -->
    &lt;context-param>
        &lt;param-name>log4jConfigLocation&lt;/param-name>
        &lt;param-value>/WEB-INF/log4j.properties&lt;/param-value>
    &lt;/context-param>   
 &lt;!--========================================================================
        Filters
    =========================================================================-->

    &lt;filter>
        &lt;filter-name>encodingFilter&lt;/filter-name>
        &lt;filter-class>com.ssgly.web.filter.EncodingFilter&lt;/filter-class>
        &lt;init-param>
            &lt;param-name>encoding&lt;/param-name>
            &lt;param-value>utf-8&lt;/param-value>
        &lt;/init-param>
    &lt;/filter>
    &lt;filter-mapping>
        &lt;filter-name>encodingFilter&lt;/filter-name>
        &lt;url-pattern>*&lt;/url-pattern>
    &lt;/filter-mapping>    
 &lt;!--========================================================================
        Listeners
    =========================================================================-->

    &lt;listener>
        &lt;listener-class>
            org.springframework.web.util.Log4jConfigListener
        &lt;/listener-class>
    &lt;/listener>
    &lt;listener>
        &lt;listener-class>
            org.springframework.web.context.ContextLoaderListener
        &lt;/listener-class>
    &lt;/listener>
   
  &lt;!--========================================================================
        Servlets
    =========================================================================-->
    &lt;servlet>
        &lt;servlet-name>dispatcherServlet&lt;/servlet-name>
        &lt;servlet-class>org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class>
        &lt;load-on-startup>0&lt;/load-on-startup>
    &lt;/servlet>

    &lt;servlet-mapping>
        &lt;servlet-name>dispatcherServlet&lt;/servlet-name>
        &lt;url-pattern>*.do&lt;/url-pattern>
    &lt;/servlet-mapping>
&lt;!--========================================================================
        DWR 配置
    =========================================================================-->
	&lt;!--配置DWR拦截器-->   
	 &lt;servlet>   
		  &lt;servlet-name>dwr-invoker&lt;/servlet-name>   
		  &lt;servlet-class>org.directwebremoting.servlet.DwrServlet&lt;/servlet-class>   
		  &lt;init-param>   
		   &lt;param-name>debug&lt;/param-name>   
		   &lt;param-value>true&lt;/param-value>   
		  &lt;/init-param>
		  &lt;init-param>
	        &lt;param-name>classes&lt;/param-name>
	        &lt;param-value>java.lang.Object&lt;/param-value>
	      &lt;/init-param>
	      &lt;load-on-startup>100&lt;/load-on-startup>
	 &lt;/servlet>   
	 &lt;servlet-mapping>   
	  &lt;servlet-name>dwr-invoker&lt;/servlet-name>   
	  &lt;url-pattern>/dwr/*&lt;/url-pattern>   
	 &lt;/servlet-mapping>
 &lt;!--========================================================================
        Session
    =========================================================================-->

    &lt;session-config>
        &lt;session-timeout>30&lt;/session-timeout>
    &lt;/session-config>

     
 
 
&lt;/web-app>


</pre><br />二是：bean生成的配置。model-config.xml<br /><pre name="code" class="java">
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" 
 "http://www.springframework.org/dtd/spring-beans.dtd"> 
 &lt;beans>
     
     &lt;bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        &lt;property name="locations">
            &lt;list>
                &lt;value>/WEB-INF/jdbc.properties&lt;/value>                
            &lt;/list>
        &lt;/property>
    &lt;/bean>
     
   &lt;bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        &lt;property name="driverClassName" value="${jdbc.driver}" />
        &lt;property name="url" value="${jdbc.url}" />
        &lt;property name="username" value="${jdbc.username}" />
        &lt;property name="password" value="${jdbc.password}" />
    &lt;/bean>    


    &lt;bean id="sessionFactory"
                 class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"  destroy-method="close">
            &lt;property name="dataSource">
                 &lt;ref local="myDataSource" />
            &lt;/property>
            &lt;property name="mappingResources">
                &lt;list>
                   &lt;value> com/ssgly/model/Region.hbm.xml&lt;/value>                
			    &lt;/list>
            &lt;/property>
            &lt;property name="hibernateProperties">
              &lt;props>
              	&lt;prop key="connection.characterEncoding">utf-8&lt;/prop>
                &lt;prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect&lt;/prop>
                &lt;prop key="hibernate.jdbc.batch_size">50&lt;/prop> 
                &lt;prop key="hibernate.show_sql">true&lt;/prop>
                &lt;prop key="hibernate.query.factory_class">org.hibernate.hql.classic.ClassicQueryTranslatorFactory&lt;/prop>
                &lt;/props>
            &lt;/property>
        &lt;/bean>
  
    &lt;bean id="transactionManager" 
          class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
        &lt;property name="sessionFactory"> 
            &lt;ref bean="sessionFactory"/> 
        &lt;/property> 
    &lt;/bean>
    
    &lt;bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
	     &lt;property name="sessionFactory"> &lt;ref bean="sessionFactory"/> &lt;/property>
    &lt;/bean>
    
 
     &lt;bean id="regionDao"  class="com.ssgly.dao.RegionDAOImpl">
        &lt;property name="hibernateTemplate"> 
            &lt;ref bean="hibernateTemplate"/>
        &lt;/property>            
     &lt;/bean>									 
   &lt;bean id="businessService" class="com.ssgly.business.impl.BusinessServiceImpl">
   	   &lt;property name="regionDAO">&lt;ref  bean="regionDao" />&lt;/property>
   	   
   &lt;/bean>
   
   &lt;bean id="todoSsglyService"  class="com.ssgly.ext.ToDoImpl">
        &lt;property name="businessServiceImpl"> 
            &lt;ref bean="businessService"/>
        &lt;/property>            
   &lt;/bean>
   
   
&lt;/beans>
</pre><br />三是：servlet配置 dispatcherServlet-servlet.xml<br /><pre name="code" class="java">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN" 
 "http://www.springframework.org/dtd/spring-beans.dtd"> 

&lt;beans>
    &lt;!--============================================================================
        URL Mapping configuration
    =============================================================================-->

    &lt;bean id="beanNameUrlMapping"
        class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
        &lt;property name="alwaysUseFullPath" value="true" />
    &lt;/bean>
   &lt;!--============================================================================
        Velocity configuration
    =============================================================================-->

    &lt;bean id="viewResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
        &lt;property name="contentType">&lt;value>text/html;charset=GBK&lt;/value>&lt;/property>
    &lt;/bean>

    &lt;bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
        &lt;property name="configLocation" value="/WEB-INF/velocity.properties" />
        &lt;property name="resourceLoaderPath" value="/" />
    &lt;/bean>
 
    &lt;bean id="treeRegionServlet"  name="/treeRegionServlet.do" class="com.ssgly.web.TreeRegionServlet">
        &lt;property name="businessService">
            &lt;ref bean="businessService"/>
        &lt;/property>
    &lt;/bean>
&lt;/beans>
</pre><br />    有了这些xml的配置。Spring能将三层很好地组合起来。以上是java部分。还没有讲到extJs。extJs可以接受asp、php、java等服务器端生成的json格式的对象。就java来说 ，extJs能接受三种方式的json对象，一是servlet中拼接json对象；其次是引用json lib 包；三是DWR方式，绕过Controller（就Spring来说）或servlet，在javascript中 直接调用java业务逻辑层中的方法（通过DWR引擎），利用dwr代理或者javascript 回调函数返回json对象并在页面展示。<br />    本人采用了第三种DWR方式实现ExtJs生成树。要使用dwr 就的要在以上几个配置文件中配置DWR（已配）。具体的下次再说吧。<br />    今天就写到这里吧。不知写的怎么样？有朋友关注这一块？若支持，请鼓励一下；写的不好、不对或不懂的地方，请拍砖。（续）<br /><br />    抱歉啊，这几天忙着考驾照，把这事给耽搁啊。书接上回吧。<br />【四】基于Spring方式的DWR配置说明。 <br /> 一、首先在WEB.xml中配置dwr拦截器 代码如下（节选）：<br /><pre name="code" class="java">
&lt;!--配置DWR拦截器-->   
	 &lt;servlet>   
             &lt;servlet-name>dwr-invoker&lt;/servlet-name>   
	  &lt;servlet-class>org.directwebremoting.servlet.DwrServlet&lt;/servlet-class>   
		  &lt;init-param>   
		   &lt;param-name>debug&lt;/param-name>   
		   &lt;param-value>false&lt;/param-value>   
		  &lt;/init-param>
		  &lt;init-param>
	        &lt;param-name>classes&lt;/param-name>
	        &lt;param-value>java.lang.Object&lt;/param-value>
	      &lt;/init-param>
	      &lt;load-on-startup>100&lt;/load-on-startup>
	 &lt;/servlet>   
	 &lt;servlet-mapping>   
	  &lt;servlet-name>dwr-invoker&lt;/servlet-name>   
	  &lt;url-pattern>/dwr/*&lt;/url-pattern>   
	 &lt;/servlet-mapping>
</pre><br />二、dwr.xml的配置。这里将Spring管理的bean映射成javascipt操作的对象。更直观的说法就是使得页面中javascript能直接使用java中对象的方法。代码如下:<br /><pre name="code" class="java">
 &lt;?xml version="1.0" encoding="utf-8"?>
&lt;!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"
	"http://getahead.ltd.uk/dwr/dwr20.dtd">

&lt;dwr>
    &lt;allow>
    	&lt;convert converter="bean"  match="com.ssgly.model.*"/>
    	&lt;convert converter="map" match="org.directwebremoting.convert.MapConverter"/> 
    	&lt;create creator="spring" javascript="treeBusinessService">
    	  &lt;param name="beanName" value="businessService"/>
		  &lt;include method="getAllChildren" />
		&lt;/create>
	&lt;/allow>
  
&lt;/dwr>
</pre><br /><br />    从上面的代码可以看出，javascript使用treeBusinessService.getAllChildren 方法就能够直接取出 Spring维持的业务逻辑层定义的bean----- businessService。从而完成了DWR的功能。这里当然存在安全问题，在这里暂时没有讨论，关于如何在DWR中进行安全控制，大家可以参考有关文档。本文暂不考虑。<br />【五】ext和服务器端交互的机制和具体实现<br />    一般说来，按照上面DWR的配置，就已经实现了在页面中使用java的方法。但java方法执行后生成的List 传回到页面还需要靠回调函数实现。例如下面代码就是包含了回调函数的测试页。<br /><pre name="code" class="java">
&lt;html>
&lt;head>      
    &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8">   
&lt;title>ExtJS－树示例&lt;/title>
&lt;link rel="stylesheet" type="text/css" href="ext2/resources/css/ext-all.css" />
&lt;script type="text/javascript" src="ext2/adapter/ext/ext-base.js">&lt;/script>
&lt;script type="text/javascript" src="ext2/ext-all.js">&lt;/script>
 
<pre name="code" class="java">&lt;script type="text/javascript" src="dwr/interface/treeBusinessService.js ">&lt;/script>
&lt;script type="text/javascript" src="dwr/engine.js ">&lt;/script>
&lt;script type="text/javascript" src="dwr/util.js ">&lt;/script></pre> <br />&lt;script type="text/javascript"><br />	 	<br />	treeBusinessService.getAllChildren(1,function(ret){<br />	                                 alert("一共有"+ret.length+"个子节点");<br />	                               });<br /><br />&lt;/script><br />&lt;/head><br />	<br />&lt;body><br />&lt;div id="tree-div">&lt;/div>     <br />&lt;/body><br />&lt;/html><br /></pre><br /><br />现在分析一下上面页面主要代码：<br /><br /><pre name="code" class="java">
&lt;script type="text/javascript" src="dwr/interface/treeBusinessService.js ">&lt;/script>
 
</pre><br />这句中的treeBusinessService就是DWR.xml中定义的<pre name="code" class="java">&lt;create creator="spring" javascript="treeBusinessService"></pre><br /><br />下面两句是使用DWR所必需的，原样加上即可。<br /><pre name="code" class="java">
 &lt;script type="text/javascript" src="dwr/engine.js ">&lt;/script>
 &lt;script type="text/javascript" src="dwr/util.js ">&lt;/script>
</pre><br />有了上面的这些DWR配置，就能够以DWR的方式使用java的方法啦：<br /><pre name="code" class="java">
&lt;script type="text/javascript">
	 	
	treeBusinessService.getAllChildren(1,function(ret){
	                                 alert("一共有"+ret.length+"个子节点");
	                               });

&lt;/script>

</pre><br />   function(ret)就是回调函数。因为treeBusinessService.getAllChildren执行的结果是List类型，DWR解析List到页面应该是javascript的对象数组，所以ret应该是个数组，ret.length是这个数组的长度。<br /><br />   上面的例子只不过是原理性的介绍，帮助我们理解javascript如何和后台进行的交互。真正要实现DWRTree 还需要专门的DWRTreeLoader代理。下面这段代码很是重要，参考了ext官方bbs上的代码，并做了修改。先提供如下：<br /><pre name="code" class="java">
Ext.tree.DWRTreeLoader = function(config) {
  Ext.tree.DWRTreeLoader.superclass.constructor.call(this, config);
};

Ext.extend(Ext.tree.DWRTreeLoader, Ext.tree.TreeLoader, {
   args:[],
   requestData : function(node, callback) {
    if (this.fireEvent("beforeload", this, node, callback) !== false) {

     
      var callParams = new Array();
      var success = this.handleResponse.createDelegate(this, [node, callback], 1);
      var error = this.handleFailure.createDelegate(this, [node, callback], 1);
      callParams.push(node.id);
      callParams.push({callback:success, errorHandler:error});

      //todo: do we need to set this to something else?
      this.transId=true;
      this.dataUrl.apply(this, callParams);
    } else {
      // if the load is cancelled, make sure we notify
      // the node that we are done
      if (typeof callback == "function") {
        //alert(callback);
        callback();
      }
    }
  },
    processResponse : function(response, node, callback){
        try {
          for(var i = 0; i &lt; response.length; i++){
                var n = this.createNode(response[i]);
                if(n){
                    node.appendChild(n);
                }
            }
            if(typeof callback == "function"){
                callback(this, node);
            }
        }catch(e){
            this.handleFailure(response);
        }
    },

    handleResponse : function(response, node, callback){
        this.transId = false;
        this.processResponse(response, node, callback);
        this.fireEvent("load", this, node, response);
    },

    handleFailure : function(response, node, callback){
        this.transId = false;
        this.fireEvent("loadexception", this, node, response);
        if(typeof callback == "function"){
            callback(this, node);
        }
    }

});  

</pre><br /><br />上面的代码可以直接在项目中使用，无需修改。<br />【六】最终DWRTree的实现包括 tree.js和 tree.html<br />tree.js完整代码如下：<br /><pre name="code" class="java">
 Ext.onReady(function(){ 
  
Ext.tree.DWRTreeLoader = function(config) {
  Ext.tree.DWRTreeLoader.superclass.constructor.call(this, config);
};

Ext.extend(Ext.tree.DWRTreeLoader, Ext.tree.TreeLoader, {
   args:[],
   requestData : function(node, callback) {
    if (this.fireEvent("beforeload", this, node, callback) !== false) {

     
      var callParams = new Array();
      var success = this.handleResponse.createDelegate(this, [node, callback], 1);
      var error = this.handleFailure.createDelegate(this, [node, callback], 1);
      callParams.push(node.id);
      callParams.push({callback:success, errorHandler:error});

      //todo: do we need to set this to something else?
      this.transId=true;
      this.dataUrl.apply(this, callParams);
    } else {
      // if the load is cancelled, make sure we notify
      // the node that we are done
      if (typeof callback == "function") {
        //alert(callback);
        callback();
      }
    }
  },
    processResponse : function(response, node, callback){
        try {
          for(var i = 0; i &lt; response.length; i++){
                var n = this.createNode(response[i]);
                if(n){
                    node.appendChild(n);
                }
            }
            if(typeof callback == "function"){
                callback(this, node);
            }
        }catch(e){
            this.handleFailure(response);
        }
    },

    handleResponse : function(response, node, callback){
        this.transId = false;
        this.processResponse(response, node, callback);
        this.fireEvent("load", this, node, response);
    },

    handleFailure : function(response, node, callback){
        this.transId = false;
        this.fireEvent("loadexception", this, node, response);
        if(typeof callback == "function"){
            callback(this, node);
        }
    }

});  


var myTree = new Ext.tree.TreePanel({   
    	el:Ext.getBody(),  
        autoScroll:true,
        animate:true,
        width:'300px',
        height:'800px',
        enableDD:true,
        containerScroll: true, 
		root:new Ext.tree.AsyncTreeNode({
             text: '单位',
             draggable:false,
             id:'1' }),
        loader:new Ext.tree.DWRTreeLoader({ 
	               dataUrl:treeBusinessService.getAllChildren, 
			       listeners : {
			                  'beforeload' : function( node) {
				                   myTree.getLoader().args[0]=(node.id!='root'?node.id:"1");
			                    }
		           }
			   })
    });
	
	myTree.render();


    
});
</pre><br />提个醒：这句<pre name="code" class="java"> myTree.getLoader().args[0]=(node.id!='root'?node.id:"1");
</pre>不能错哦，它是和 DWRTreeLoader耦合的。<br /><br />tree.html是这样的：<br /><pre name="code" class="java">
&lt;html>
&lt;head>      
    &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8">   
&lt;title>ExtJS－树示例&lt;/title>
&lt;link rel="stylesheet" type="text/css" href="ext2/resources/css/ext-all.css" />
&lt;script type="text/javascript" src="ext2/adapter/ext/ext-base.js">&lt;/script>
&lt;script type="text/javascript" src="ext2/ext-all.js">&lt;/script>
 
&lt;script type="text/javascript" src="dwr/interface/treeBusinessService.js ">&lt;/script>
&lt;script type="text/javascript" src="dwr/engine.js ">&lt;/script>
&lt;script type="text/javascript" src="dwr/util.js ">&lt;/script>
&lt;script type="text/javascript" src="js/tree.js">&lt;/script> 
  
&lt;/head>
	
&lt;body>
 
&lt;/body>
&lt;/html>
</pre><br /><br />  好了，基于Spring+hibernate+dwr+EXTJs的DWRTreeLoader的实现就是这样。本想提供完整代码下载。但想来想去还是让读者自己结合我的文章边做边体会比较好。说不定还能优化我的代码呢。你说是吗？<br /><br />  还有comBoboxTree的实现没有写。也不知大家感兴趣没？还是欢迎大家多提意见吧。
          <br/>
          <span style="color:red;">
            <a href="http://crabboy.javaeye.com/blog/162551#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 15 Feb 2008 20:56:42 +0800</pubDate>
        <link>http://crabboy.javaeye.com/blog/162551</link>
        <guid>http://crabboy.javaeye.com/blog/162551</guid>
      </item>
      <item>
        <title>hibernate 多条件组合查询 之 sql 拼接</title>
        <author>crabboy</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://crabboy.javaeye.com">crabboy</a>&nbsp;
          链接：<a href="http://crabboy.javaeye.com/blog/130279" style="color:red;">http://crabboy.javaeye.com/blog/130279</a>&nbsp;
          发表时间: 2007年10月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span></span></span><strong><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(127, 0, 85);">public</span></strong><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"> </span><strong><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(127, 0, 85);">static</span></strong><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"> </span><strong><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(127, 0, 85);">void</span></strong><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"> main(String[] args) {</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Session session = </span><strong><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(127, 0, 85);">null</span></strong><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">;</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Transaction tx = </span><strong><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(127, 0, 85);">null</span></strong><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">;</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>List list = </span><strong><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(127, 0, 85);">null</span></strong><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">;</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Criteria criteria = </span><strong><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(127, 0, 85);">null</span></strong><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">;</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p>&nbsp;</o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><strong><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(127, 0, 85);">try</span></strong><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"> {</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p>&nbsp;</o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>session = HibernateSessionFactory.<em>getSession</em>();</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>tx = session.beginTransaction();</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p>&nbsp;</o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DetachedCriteria detachedCriteria = DetachedCriteria</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.<em>forClass</em>(InfoTab.</span><strong><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(127, 0, 85);">class</span></strong><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">);</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>String sql=</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot; 1=1 &quot;</span><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">;</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Integer pareaId = 0; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">父地区；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Integer careaId = 0; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">子地区；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Integer categoryId = 0; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">类别；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>String infoPrivider = </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span style="font-size: 10pt; color: rgb(42, 0, 255); font-family: 宋体;">中介</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">来源；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>String houseType= </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span style="font-size: 10pt; color: rgb(42, 0, 255); font-family: 宋体;">地下室</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">房屋类型；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Integer hxBedRoom=0; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">室；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Integer hxLivingRoom=0; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">厅；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>String hzHouseStatus=</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span style="font-size: 10pt; color: rgb(42, 0, 255); font-family: 宋体;">有房出租</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">合租类型</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">;</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span>&nbsp;&nbsp;&nbsp; </span>String hzRequestSex=</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span style="font-size: 10pt; color: rgb(42, 0, 255); font-family: 宋体;">男</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">性别要求；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>String fixUp=</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span style="font-size: 10pt; color: rgb(42, 0, 255); font-family: 宋体;">尚未</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">装修程度</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">;</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Integer lcHeightMolecuse=0; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">楼层；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>String orientation=</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span style="font-size: 10pt; color: rgb(42, 0, 255); font-family: 宋体;">东南</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">朝向要求</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">;</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Integer buildArea=2000; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">建筑面积；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Integer useArea=80; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">使用面积；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Integer rentalDigit=2000; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">租金</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">/</span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">价格；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>String title= </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span style="font-size: 10pt; color: rgb(42, 0, 255); font-family: 宋体;">出租</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;</span><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">; </span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(63, 127, 95);">// </span><span style="font-size: 10pt; color: rgb(63, 127, 95); font-family: 宋体;">标题；</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><strong><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(127, 0, 85);">if</span></strong><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">(pareaId!=0)</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>sql+=</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot;pareaId=&quot;</span><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"> + pareaId;</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><strong><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(127, 0, 85);">if</span></strong><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">(careaId!=0)</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>sql+=</span><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(42, 0, 255);">&quot; and careaId=&quot;</span><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"> + careaId;</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div class="MsoNormal" align="left" style="text-align: left;"><span courier="" lang="EN-US" style="font-size: 10pt; color: black;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><strong><span courier="" lang="EN-US" style="font-size: 10pt; color: rgb(127, 0, 85);">if</span></strong><span courier="" lang="EN-US" style="font-size: 10pt; color: black;">(categoryId!=0)</span><span courier="" lang="EN-US" style="font-size: 10pt;"><o:p></o:p></span></div>
<div 