<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>驾驭无形的力量—软件艺法思考</title>
    <description>对软件架构设计开发的技艺有所思考?
对软件科研推广应用的前景有所预感?
让我们来一起交流, 探索.</description>
    <link>http://softforce.group.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>实例观察网络模型与关系模型对现实世界的建模差异</title>
        <author>歆渊</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://complystill.javaeye.com">歆渊</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/126681" style="color:red;">http://softforce.group.javaeye.com/group/blog/126681</a>&nbsp;
          发表时间: 2007年09月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          我感觉受 主流/传统的 Object Orientation 对 领域模型设计 的影响, 以及 SQL 对 关系模型设计 的影响, 目前领域模型基本都设计为 "网络模型" 也就是更倾向于 传统的数据结构. <br /><br />举个例子, 比如要描述一颗螺丝 s1 和一颗螺母 c1, 以及把它们拧在一起的关系. <br /><br />如果按照网络模型(传统数据结构)的思路, 那么就必须同时有一个把螺丝拧进螺母(s1.cap = c1)和一个把螺母拧上螺丝的动作(c1.screw = s1), 显然这跟现实世界的逻辑思维是有差别的.<br /><br />反过来如果按照关系模型的思路, 只要一个建立拧接关系的动作 (new Screwing(s1, c1)), 就跟现实逻辑是恰好符合的.<br /><br />不过在通用OO语言基础上实现关系模型的语义, 还是要费些周折, 不过也不是不可能. <a href="http://www.ableverse.org/articles/orkm.pdf" target="_blank">Object Relation Kin Model</a> 就是一个结合通用OO语言与关系模型的例子.
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/126681#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 24 Sep 2007 16:53:37 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/126681</link>
        <guid>http://softforce.group.javaeye.com/group/blog/126681</guid>
      </item>
      <item>
        <title>Introducing Hosting Based Interfacing</title>
        <author>歆渊</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://complystill.javaeye.com">歆渊</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/124767" style="color:red;">http://softforce.group.javaeye.com/group/blog/124767</a>&nbsp;
          发表时间: 2007年09月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <strong>HBI - Hosting Based Interfacing </strong><br /><br /><br /><strong>What is (not) HBI? </strong><br /><br /><div class="quote_title">引用</div><div class="quote_div">HBI is about interoperability among distributed applications (software components), built with same or different technologies. As the name implies, HBI is an architecture that software components communicate with each others by hosting the execution of logics from peers. HBI is to get rid of synchronous access to remote resources, make all code executed natively and locally (in both concept and practice) whereas asynchronously. So transactional logics can be naturally grouped into atomic units and performed in parallel ways. On optimistic commit failures, transactions are possible to be retried automatically and transparently. At the same time performance drop and pitfalls due to synchronous execution and distributed data cache are get rid of, as well.<br /><br />SQL is essentially semi-HBI: There is an interesting fact that wherever you wrote your SQL code, it is executed in the server environment, and you know your SQL always access local resources like tables, views and stored-procedures etc. SQL transactions naturally consist of arbitrary statements between two COMMITs. Pure SQL transactions are possible to be transparently retried on optimistic commit failures.<br /><br />On the contrary is IBI - Invocation Based Interfacing. Those paradigms try to hide resources behind some mechanisms so that access to resources are wrapped/encapsulated in synchronous ways, regardless they are local or remote. Some define service invocation interfaces, like RMI (including EJB), Web-Service, where remote routines encapsulate their resources and are wrapped like client-local code. Some allow data resources distributed to client environment and wrapped with client-local library code that transparently make data available, handle validity, and manage consistency, like various OODBs, ORM. Transactions can rarely be transparently retried on these infrastructures. </div><br /><br /><br /><br /><strong>What does HBI cost? </strong><br /><br /><div class="quote_title">引用</div><div class="quote_div">Distribution and concurrency/parallel become explicit, asynchronous complexity instead of implicit, synchronous complexity.<br /><br />Synchronous programming habit will be broken, programmers will have to consciously know that some blocks of their code will run asynchronously at environments (domains) other than the local application they are developing. Code relies on the result of some remote manipulations can not be programmed as a subsequent block of that manipulation code, but must be implemented as local task agent objects that the remote peer can send back to indicate the result.<br /><br />Higher security profile. Applications need to enforce sandboxes to host executions of objects from other domains, against malfunctioning peers and hostile attacks. </div><br /><br /><br /><br /><strong>What HBI benefits? </strong><br /><br /><div class="quote_title">引用</div><div class="quote_div">The architecture of large RAM/storage shared by many CPUs/cores is best benefited. Large data sets in a single memory space and local storage are shared as-is to all domains requiring them, manipulations to these resources are hosted by local CPUs/cores having direct access to them. This is the most efficient way for distributed domain resource sharing. <br /><br />As a result, performance is a biggest hit. All data and logics become local and native, and can be greatly optimized with explicit parallel (parallel candidates are expressed by application code as a side effect). No data replicated anymore, large amount of redundant memory and bandwidth saved. <br /><br />Much less pitfalls due to distribution of objects. Neither objects are distributed anymore, nor do they need to be transfered over wire, objects now always identify themselves at where they actually are, no shadow copies or stubs or proxies used to create subtle errors and harden debugging. <br /><br />Server applications are much more stable. Most new client requirements those used to need service API changes in traditional approaches now can be unilaterally achieved by modifying only the client application. <br /><br />Client applications can go much richer without resistance from the server side, do not need to change/restart server applications (i.e. less permissions/efforts required) in order to evolve client applications. <br /><br />Client applications have their own rich domain models that focus on their own functionalities, much better separated from functionalities like persistence and work flows those server applications need to care. Client applications can focus on their own domain model which is regarded by server applications by translating server domain model changes to client behaviors through delivery of task agent life scripts. <br /><br />More effective Object Orientation. No data packet based protocol anymore, all logics become behaviors of either domain objects or agent objects triggered by task agent life script. <br /><br />P2P communications become more natural. Clients are also domains, they are at the same priority of server components in inter-domain communications. <br /><br />Much more realtime-interactive features can be naturally implemented to enhance user experience. Built-in server-push and P2P-push ability well enable it. </div>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/124767#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/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 17 Sep 2007 16:21:40 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/124767</link>
        <guid>http://softforce.group.javaeye.com/group/blog/124767</guid>
      </item>
      <item>
        <title>最小权限原则应用于面向对象的软件设计开发</title>
        <author>歆渊</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://complystill.javaeye.com">歆渊</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/109642" style="color:red;">http://softforce.group.javaeye.com/group/blog/109642</a>&nbsp;
          发表时间: 2007年08月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          偶然看到Wiki百科的 <a href="http://en.wikipedia.org/wiki/Lua_(programming_language)" target="_blank">Lua</a> 词条, 注意到它的这个特性:<br /><br /><div class="quote_title">引用</div><div class="quote_div">Lua allows ...; and full lexical scoping allows fine-grained <a href="http://en.wikipedia.org/wiki/Information_hiding" target="_blank">information hiding</a> to enforce <a href="http://en.wikipedia.org/wiki/Principle_of_least_privilege" target="_blank">the principle of least privilege</a>.</div><br /><br />不过比较遗憾的是, 通过这里链接过去的 <a href="http://en.wikipedia.org/wiki/Principle_of_least_privilege" target="_blank">http://en.wikipedia.org/wiki/Principle_of_least_privilege</a> 词条中的描述, 似乎这个 <strong>最小权限原则</strong> 没怎么被用于软件设计开发方法学, 虽然很早就提出来了, 但主要描述的是在系统设计领域的应用.<br /><br />我最近正好在做 HBI 的 编程语言/平台 互操作性架构, 目前在做 Java 和 ActionScript 3.0 的互操作框架. 而发现 AS3 很多有意思的地方. 其中可以在程序开发中用来实现 <strong>最小权限原则</strong> 的就是 AS3 语言中的 namespace 机制. 刚看到这个机制的时候我是眼前一亮的感觉, 因为很早以前就觉得 Java 在语法元素方面缺乏这个层次的 <a href="http://en.wikipedia.org/wiki/Information_hiding" target="_blank">information hiding</a> 能力, 但是一直没机会研究这些其他的语言, 也就没有了解到已经存在的实现, 只是脑子里模模糊糊的有个感觉, 如果xxx那样增强一下会更好. 而在最近出来的 ActionScript 3.0 里, 已经有了明确成熟的实现了.<br /><br />这里很简单的描述一下OO时如果没有足够好 <a href="http://en.wikipedia.org/wiki/Information_hiding" target="_blank">information hiding</a> 的话所带来的后果, 一个非常简单且常见的例子就是在Hibernate中, 你必须在你的持久Java类中定义一个 identity 字段用作 primary key, 并且要暴露一个 public 的 setter 方法, 好让 Hibernate 去给它赋值; 类似的, 对于关联对象你也要自己定义这么一个集合field, 然后暴露 public setter 方法, 只是为了给 Hibernate 方便. 显然所有的人都能看到这些个 public 的方法, 也可以完全没有编译错误的去调用它们, 而只有脑袋里绷住了一根弦儿, 说这个是给 H 用的, 不是给我用的, 才不至于犯傻或者手误去敲错代码, 盛行的带自动提示的Java IDE让这种错误的机率又提高了不少.<br /><br />这个看起来不像是很严重的问题, 但是在大规模的软件开发维护中毕竟小的出错率也能贡献大量的错误, 况且要占用每个程序员大脑中的一根神经, 不能更好的集中到业务逻辑上去. 就像现在很多流行编程语言, 通过扔掉指针, 实现垃圾回收器从而把程序员从释放内存的负担中解放出来一样, 早晚也得把人类程序员从考虑各种 API 的调用顺序, 适用性 以及 Side Effect的负担中解放出来, 有更多精力专注于业务逻辑的正确实现.<br /><br />而这里考虑的 <strong>最小权限原则</strong>, 是其中一个方面. 那么怎么实现呢?<br /><br />说明在 ActionScript 3.0 中如何通过 namespace 实现最小权限原则之前, 简单介绍一下AS3的背景:<br /><br />在 3.0 以前, ActionScript 2.0 和 1.0 一直是 Flash Player 的专有编程语言. 最开始并没有版本, 而 AS2 出来的时候加入了大量的实质性面向对象元素, 所以为了加以区别, 就把以前版本的AS称为 1.0. 其实到目前的 AS 3.0 为止它作为Flash的专有语言的情况也没有改变, 只不过其新主 Adobe 和 Mozilla 联手, 准备以开源的形式发展 AS3. 名义上是两家共同开发 ECMAScript 第4版 的规范以及虚拟机实现, 然后Adobe把它用在Flash里, Mozilla把它用在FireFox的SpiderMonkey里, 所以AS3的规范称自己是 "基于" ECMA 规范. 而实际上 ECMAScript 第4版 现在还只是draft, AS3 却已经投入市场了, 并且 Mozilla 上关于 es4 的wiki内容也全是从Adobe资料导入的. 可见整个局势主要还是由Adobe推动的.<br /><br />另外也必须说一下 AS3 的革命性. 如果你看一段官方推荐风格的 AS3 代码, 就会发现它已经 非常 非常 像 Java. 最早的 ActionScript (1.0) 只是一些最简单的脚本, 那时主要也是给不是程序员的艺术创作人员用的. 到了 AS 2.0, 面向对象被引入了, 但它实质上是动态脚本语言, 虽然已经有了类的概念和<strong>class</strong>关键字, 但对象支持还是基于类似JavaScript的prototype机制, 动态继承. 而到了 AS 3.0, 按照官方的说法, 它同时支持静态类型, 基于类的继承方式, 以及动态类型, 基于prototype的继承方式; 虽然后者是AS 3以前唯一支持的方式, 但是在 AS3 中, 并不推荐使用这种方式, 而是建议全部采用前者的静态类型方式. 涉及到这么做的动机时, 官方资料有提到说这是因为用Flash开发的应用规模越来越大. 而即使是在受支持的动态类型机制下, AS3 也并不是完全兼容 AS2, 在事件模型和语法含义上都有打破兼容性的地方. 这在商业意义上的损失无疑是巨大的, 即使 AS3 应用的执行效率要远远高于以前版本, 兼容性方面的损失恐怕也难以弥补. 另外虽然号称是基于 ECMAScript 4, 但是 AS3 默认支持的是 <strong>strict</strong> dialect 而非 standard es4. <strong>strict dialect</strong> 实质上主要就是 <strong>静态类型+严格语法检查</strong>. 由此可以看出 AS3 已经不是原本的动态类型脚本语言, 而是一种 <strong>动静结合, 静态为主, 动态为辅</strong> 的程序设计语言. 并且其静态语言特性是Adobe鼎力支持的重点.<br /><br />基本了解了 AS3 的历史和现状之后, 我们可以确信, 它目前很多特性并非只能在动态语言中实现, 而是有可能在静态语言中重现的. 至少 namespace 是如此. 那么回到 <strong>最小权限原则</strong> 的话题, 看看它可以怎么实现.<br /><br />在 AS3 中也有 public, private, protected, internal (==default) 这些权限修饰符, 并且各自含义与Java中的同名修饰符完全相同. 但是, 或许有点难以理解, 在 AS3 中它们都是内置的 namespace 而非仅仅是关键字, 编译器通过维护这些内置 namespace 的 可见/适用范围 来实现其语义. 最重要的, namespace 是 AS3 中的一等公民, 也就是说应用程序可以像定义class一样的定义自己的 namespace. 自定义的 namespace 可以放在 public, private, protected, internal 相同的位置用来限定相应语法元素的可访问性, 包括 类, 类成员方法 和 类成员变量.<br /><br />有了这件利器, 要解决前面提到的Hibernate持久类setter方法过度暴露的问题, 就显得非常容易了. 假如我们在 AS3 中实现一个 ORM 的话(虽然目前来说意义还不大, AS 因为没有线程机制, 在很多场合还不适用), 就可以定义一个 orm 专用的 namespace:<br /><br /><pre name="code" class="java">package orm
{
  public namespace ormstub;

  public class ObjectStore
  {
     ...
     public function save(o:Object):void
     {
        var pk:Object = o.getID();
        if(!pk)
        {
          pk = assignID();
          o.ormstub::setID(pk);
        }
        ...
     }
     ...
  }
}</pre><br /><br />然后应用的持久类就可以利用这个 namespace 把只暴露给orm的setter方法向系统其他部分隐藏起来:<br /><br /><pre name="code" class="java">package app
{
  import orm.ormstub;

  public class User
  {
     private var id:Object;

     public function getID():Object
     {
        return this.id;
     }

     ormstub function setID(id:Object):void
     {
        this.id = id;
     }

     ...
  }
}</pre><br /><br />或者更具 AS3 风格的程序可以写成:<br /><br /><pre name="code" class="java">package orm
{
  public namespace ormstub;

  use namespace ormstub;

  public class ObjectStore
  {
     ...
     public function save(o:Object):void
     {
        var pk:Object = o.id;
        if(!pk)
        {
          pk = assignID();
          o.id = pk;
        }
        ...
     }
     ...
  }
}

package app
{
  import orm.ormstub;

  public class User
  {
     private var _id:Object;

     public function get id():Object
     {
        return this._id;
     }

     ormstub function set id(pk:Object):void
     {
        this._id = pk;
     }

     ...
  }
}</pre>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/109642#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/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 07 Aug 2007 06:34:32 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/109642</link>
        <guid>http://softforce.group.javaeye.com/group/blog/109642</guid>
      </item>
      <item>
        <title>原创Full-Stack框架VIWO开源首发（附源码、示例、教程）</title>
        <author>viwo</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://viwo.javaeye.com">viwo</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/99735" style="color:red;">http://softforce.group.javaeye.com/group/blog/99735</a>&nbsp;
          发表时间: 2007年07月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font face="Arial">有人说不要重新发明轮子，我说你不能总用别人的轮子。也许VIWO是个木头轮子，也许VIWO不是很结实，经不起大的颠簸，也许VIWO微不足道，你甚至不屑一顾，但是我想：Struts也好Spring也好，iBatis也好，起初无非就是个冲动、想法、无奈一点一点发展起来。</font></p>
<p><font face="Arial">今天我把我写的一些小程序打成包，命名叫做VIWO开源发布在这里，说不上为中国的开源界做什么贡献，就是想抛砖引玉，能让更多的高手把你们写的东西共享出来，让大家一起学习共同进步，而不是泛泛而谈新新技术，求新求变固然无可厚非，只是&ldquo;勿在浮沙筑高台&rdquo;。或者你有兴趣拿这VIWO的源代码，添加些新功能，修改些BUG,，亦或者给几块板砖，我都会感激不尽。</font></p>
<p><font face="Arial">因为传输速度，VIWO发布包，源码，示例放在Google Code上面了（JavaEye的访问速度可能和网段有关，我用大连网通访问速度奇慢，文章发好几遍才能发全）。</font></p>
<p><font face="Arial">下载页面：<a href="http://code.google.com/p/viwo/downloads/list">http://code.google.com/p/viwo/downloads/list</a><br />
直接下载地址： <br />
完整示例：<a href="http://viwo.googlecode.com/files/VIWO_Example.rar">viwo-example.rar</a><br />
发布程序：<a href="http://viwo.googlecode.com/files/viwo-0.4.3.jar">viwo-0.4.3.jar</a><br />
源码：<a href="http://viwo.googlecode.com/files/viwo-0.4.3-src.jar">viwo-0.4.3-src.jar</a></font></p>
<p><font face="Arial"></font>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/99735#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/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 10 Jul 2007 11:57:27 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/99735</link>
        <guid>http://softforce.group.javaeye.com/group/blog/99735</guid>
      </item>
      <item>
        <title>异常处理</title>
        <author>steven_cheng</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://steven-cheng.javaeye.com">steven_cheng</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/87667" style="color:red;">http://softforce.group.javaeye.com/group/blog/87667</a>&nbsp;
          发表时间: 2007年06月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>最近刚好作了一个产品的异常处理规范，把我做的也拿出来晒晒，和大家讨论一下。</p>
<p>1、CheckException or UnCheckedException</p>
<p>个人倾向用UnCheckedException。我见过的最多的处理异常的代码就是记录日志或转换后抛出<img src="/javascripts/fckeditor/editor/images/smiley/msn/teeth_smile.gif" alt="" />，好像做其他操作的少之又少。我以前还见过有人不管三七二十一，抓到什么抛什么，结果一个接口抛出了3-5种CheckException。别扭啊，呵呵。</p>
<p>当然，最大的缺陷就是对接口调用者的使用。至少UnCheckedException可以让接口调用者选择catch还是不catch。</p>
<p>因为这是一个遗留系统，都使用了CheckedException，不过好在使用的比较规范，没有太大麻烦。</p>
<p>2、异常信息</p>
<p>因为开发者众多，异常信息五花八门，有中文的有英文的，有简单的，有复杂的。散落在各个类里，修改起来很麻烦。</p>
<p>我的处理办法是，定义异常码，异常信息和异常码一一对应，定义在properties文件里，抛出异常的地方只引用异常码。这样，如果需要修改异常信息，只要修改properties文件重新打包即可。异常码分为原因码和位置码。位置码一般用在业务逻辑类里。比如一般用到的Facad模式，可能一个接口定义了n个方法，每个方法都抛出XXXBusinessException(XXX用于区分业务子包)，抛出的异常码在代码里顺序定义即可。原因码表示某类异常，比如SQLException引起的异常都为8000。</p>
<p>异常码中原因码按包、类、接口定义，比如：前两位表示一级子包，接下来两位留给二级子包，接下来两位表示类，最后3位表示方法。</p>
<p>异常信息如果需要，可以保留现场信息。比如：&ldquo;<font face="Arial">用户[abc]已存在&rdquo;。这样的信息就比&ldquo;<font face="Arial">用户已存在&rdquo;明确。这个功能可以通过<font face="Arial">java.text.MessageFormat实现。</font></font></font></p>
<p>3、异常的链式抛出</p>
<p>即，在调用底层接口时捕获到异常，需要转成其他的异常抛出时<font size="1">，<font face="Arial">使用带Throwable的构造器。这样可以保留最原始的出错信息。</font></font></p>
<p><font size="1">异常基类代码：</font></p>
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;BaseException&nbsp;</span><span class="keyword">extends</span><span>&nbsp;Exception&nbsp;{ &nbsp;&nbsp;</span></span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">long</span><span>&nbsp;errorCode; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span>&nbsp;String[]&nbsp;args; &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp; </li>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;errorCode </span>&nbsp;</span> </li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;BaseException(</span><span class="keyword">long</span><span>&nbsp;errorCode)&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">super</span><span>(); &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.errorCode&nbsp;=&nbsp;errorCode; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp; </li>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;errorCode </span>&nbsp;</span> </li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;cause </span>&nbsp;</span> </li>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;BaseException(</span><span class="keyword">long</span><span>&nbsp;errorCode,Throwable&nbsp;cause)&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">super</span><span>(cause); &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.errorCode&nbsp;=&nbsp;errorCode; &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp; </li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;errorCode </span>&nbsp;</span> </li>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;cause </span>&nbsp;</span> </li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;args&nbsp;@see&nbsp;{@link&nbsp;java.text.MessageFormat#format(Object)} </span>&nbsp;</span> </li>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;BaseException(</span><span class="keyword">long</span><span>&nbsp;errorCode,Throwable&nbsp;cause,String[]&nbsp;args)&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">super</span><span>(cause); &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.errorCode&nbsp;=&nbsp;errorCode; &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.args&nbsp;=&nbsp;args; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/*&nbsp;(non-Javadoc) </span>&nbsp; </li>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@see&nbsp;java.lang.Throwable#getMessage() </span>&nbsp;</span> </li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;String&nbsp;getMessage()&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;message&nbsp;=&nbsp;</span><span class="string">&quot;&quot;</span><span>; &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(</span><span class="keyword">this</span><span>.args&nbsp;==&nbsp;</span><span class="keyword">null</span><span>&nbsp;||&nbsp;</span><span class="keyword">this</span><span>.args.length&nbsp;==&nbsp;</span><span class="number">0</span><span>)&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message&nbsp;=&nbsp;MessageSource.getInstance().resolveCodeWithoutArguments( &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.errorCode); &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span class="keyword">else</span><span>&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message&nbsp;=&nbsp;MessageSource.getInstance().resolveCode(</span><span class="keyword">this</span><span>.errorCode) &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.format(</span><span class="keyword">this</span><span>.args); &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">this</span><span>.errorCode+</span><span class="string">&quot;:&quot;</span><span>+message; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp; </li>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;the&nbsp;errorCode </span>&nbsp;</span> </li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">long</span><span>&nbsp;getErrorCode()&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;errorCode; &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">/** </span>&nbsp; </li>
    <li class="alt"><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;the&nbsp;args </span>&nbsp;</span> </li>
    <li class=""><span><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;String[]&nbsp;getArgs()&nbsp;{ &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;args; &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li>
    <li class=""><span>&nbsp;&nbsp;</span> </li>
    <li class="alt"><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p>其中：MessageSource这个类就是根据是否有现场信息，分别处理，得到完整异常信息表述字符串。</p>
<p>关于主贴中嵌套打印的部分，从JDK1.4开始，Throwable就是嵌套打印的，所以不必再覆盖那几个方法了。</p>
<p>现在假使，有AException 和BException，都从BaseException继承。在方法里，我们捕获了AException，需要转换成BException抛出，这时候我们就非常希望能直接用AException的信息(errorCode和args)。所以，如果再来这样一个构造器似乎更好：</p>
<div class="code_title">java 代码</div>
<div class="dp-highlighter">
<div class="bar"></div>
<ol class="dp-j">
    <li class="alt"><span><span class="keyword">public</span><span>&nbsp;BaseException(BaseException&nbsp;cause){ &nbsp;&nbsp;</span></span> </li>
    <li class=""><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.errorCode&nbsp;=&nbsp;cause.getErrorCode(); &nbsp;&nbsp;</span> </li>
    <li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.args&nbsp;=&nbsp;cause.getArgs(); &nbsp;&nbsp;</span> </li>
    <li class=""><span>}&nbsp;&nbsp;</span> </li>
</ol>
</div>
<p>但是，因为Exception有一个构造器：<font face="Arial">public Exception(Throwable cause)，所以这样的构造器就是<font face="Arial"><strong>重载(overload)</strong>，而不是<font face="Arial"><strong>覆盖(Override)</strong>。重载，入参又是父子类关系，这样的方法很容易混淆，所以就没有提供。</font></font></font></p>
<p>我按照这个异常处理规范，花了两三天时间把代码重构了一遍。似乎用起来挺好使<img src="/javascripts/fckeditor/editor/images/smiley/msn/teeth_smile.gif" alt="" /></p>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/87667#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><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><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 07 Jun 2007 14:53:43 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/87667</link>
        <guid>http://softforce.group.javaeye.com/group/blog/87667</guid>
      </item>
      <item>
        <title>计算机的二进制带符号运算为什么用0表示正数1表示负数</title>
        <author>jianfeng008cn</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://jianfeng008cn.javaeye.com">jianfeng008cn</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/87484" style="color:red;">http://softforce.group.javaeye.com/group/blog/87484</a>&nbsp;
          发表时间: 2007年06月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          以8b为例对比如下：（谁能给我补补课，说说为什么是正0负1，按照我的理解应该是正1负0更符合人类的思维，前者是进行了一次技术上的mapping了）<br /><br /><br />正号：0<br />负号：1<br /><br />原码：<br />+1 0 000 0001<br />-1 1 000 0001<br /><br />反码：<br />+1 ...<br />-1 0 111 1110<br /><br />补码：<br />+1 ...<br />-1 0 111 1111<br /><br /><br />1+(-1)=0<br /><br /> 0 000 0001<br /> 0 111 1111<br />------------<br /> 1 000 0000  = (-0)<br /><br /><br />而如果反过来就会是这样的：<br /><br />正号：1<br />负号：0<br /><br />原码：<br />+1 1 000 0001<br />-1 0 000 0001<br /><br />反码：<br />+1 ...<br />-1 1 111 1110<br /><br />补码：<br />+1 ...<br />-1 1 111 1111<br /><br /><br />1+(-1)=0<br /><br /> 1 000 0001<br /> 1 111 1111<br />------------<br />11 000 0000  = (溢出位 8b考虑为 +0)
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/87484#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><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><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 06 Jun 2007 23:03:41 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/87484</link>
        <guid>http://softforce.group.javaeye.com/group/blog/87484</guid>
      </item>
      <item>
        <title>Oracle 开发 - 6</title>
        <author>javaTo</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://devezhao.javaeye.com">javaTo</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/80436" style="color:red;">http://softforce.group.javaeye.com/group/blog/80436</a>&nbsp;
          发表时间: 2007年05月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
--[6]// Oracle Trigger
---------------------------------------------------------------------------------------------//
--实例1------------------------
--创建触发器，当用户对test表执行DML语句时，将相关信息记录到日志表
--创建测试表
CREATE TABLE test
(
	t_id   NUMBER(4),
	t_name VARCHAR2(20),
	t_age  NUMBER(2),
	t_sex  CHAR
);
--创建记录测试表
CREATE TABLE test_log
(
	l_user   VARCHAR2(15),
	l_type   VARCHAR2(15),
	l_date   VARCHAR2(30)
);
--创建触发器
CREATE OR REPLACE TRIGGER test_trigger
AFTER DELETE OR INSERT OR UPDATE ON test
DECLARE
	v_type test_log.l_type%TYPE;
BEGIN
	IF INSERTING THEN  --INSERT触发
		v_type := 'INSERT';
		DBMS_OUTPUT.PUT_LINE('记录已经成功插入，并已记录到日志');
	ELSIF UPDATING THEN  --UPDATE触发
		v_type := 'UPDATE';
		DBMS_OUTPUT.PUT_LINE('记录已经成功更新，并已记录到日志');
	ELSIF DELETING THEN
		v_type := 'DELETE';
		DBMS_OUTPUT.PUT_LINE('记录已经成功删除，并已记录到日志');
	END IF;
	INSERT INTO test_log VALUES(user,v_type,
				    TO_CHAR(sysdate,'yyyy-mm-dd hh24:mi:ss'));
END;
/
--下面我们来分别执行DML语句
INSERT INTO test VALUES(101,'zhao',22,'M');
UPDATE test SET t_age = 30 WHERE t_id = 101;
DELETE test WHERE t_id = 101;
--然后查看效果
SELECT * FROM test;
SELECT * FROM test_log;

--实例2------------------------
--创建触发器，它将映射emp表中每个部门的总人数和总工资
--创建映射表
CREATE TABLE dept_sal
	AS
	SELECT deptno,COUNT(empno) AS total_emp,SUM(sal) AS total_sal FROM emp GROUP BY deptno;
DESC dept_sal;
--创建触发器
CREATE OR REPLACE TRIGGER emp_info
AFTER INSERT OR UPDATE OR DELETE ON emp
DECLARE
	CURSOR cur_emp IS
	  SELECT deptno,COUNT(empno) AS total_emp,SUM(sal) AS total_sal FROM emp GROUP BY deptno;
BEGIN
	DELETE dept_sal;  --触发时首先删除映射表信息
	FOR v_emp IN cur_emp LOOP
		--DBMS_OUTPUT.PUT_LINE(v_emp.deptno || v_emp.total_emp || v_emp.total_sal);
		--插入数据
		INSERT INTO dept_sal
			VALUES(v_emp.deptno,v_emp.total_emp,v_emp.total_sal);
	END LOOP;
END;
/
--对emp表进行DML操作
INSERT INTO emp(empno,deptno,sal) VALUES('123','10',10000);
SELECT * FROM dept_sal;
DELETE EMP WHERE empno=123;
SELECT * FROM dept_sal;

--实例3------------------------
--创建触发器，它记录表的删除数据
--创建表
CREATE TABLE employee
(
	id   VARCHAR2(4)  NOT NULL,
	name VARCHAR2(15) NOT NULL,
	age  NUMBER(2)    NOT NULL,
	sex  CHAR         NOT NULL
);
DESC employee;
--插入数据
INSERT INTO employee VALUES('e101','zhao',23,'M');
INSERT INTO employee VALUES('e102','jian',21,'F');
--创建记录表
CREATE TABLE old_employee AS
	SELECT * FROM employee;
DESC old_employee;
--创建触发器
CREATE OR REPLACE TRIGGER tig_old_emp
AFTER DELETE ON employee  --
FOR EACH ROW  --语句级触发，即每一行触发一次
BEGIN
	INSERT INTO old_employee
		VALUES(:old.id,:old.name,:old.age,:old.sex);  --:old代表旧值
END;
/
--下面进行测试
DELETE employee;
SELECT * FROM old_employee;

--实例4------------------------
--创建触发器，利用视图插入数据
--创建表
CREATE TABLE tab1 (tid NUMBER(4) PRIMARY KEY,tname VARCHAR2(20),tage NUMBER(2));
CREATE TABLE tab2 (tid NUMBER(4),ttel VARCHAR2(15),tadr VARCHAR2(30));
--插入数据
INSERT INTO tab1 VALUES(101,'zhao',22);
INSERT INTO tab1 VALUES(102,'yang',20);
INSERT INTO tab2 VALUES(101,'13761512841','AnHuiSuZhou');
INSERT INTO tab2 VALUES(102,'13563258514','AnHuiSuZhou');
--创建视图连接两张表
CREATE VIEW tab_view AS
	SELECT tab1.tid,tname,ttel,tadr FROM tab1,tab2
		WHERE tab1.tid = tab2.tid;
--创建触发器
CREATE OR REPLACE TRIGGER tab_trigger
INSTEAD OF INSERT ON tab_view
BEGIN
	INSERT INTO tab1(tid,tname) VALUES(:new.tid,:new.tname);
	INSERT INTO tab2(ttel,tadr) VALUES(:new.ttel,:new.tadr);
END;
/
--现在就可以利用视图插入数据
INSERT INTO tab_view VALUES(105,'zhaoyang','13886681288','beijing');
--查看效果
SELECT * FROM tab_view;

--实例5------------------------
--创建触发器，比较emp表中更新的工资
CREATE OR REPLACE TRIGGER sal_emp
BEFORE UPDATE ON emp
FOR EACH ROW
BEGIN
	
	IF :OLD.sal > :NEW.sal THEN
		DBMS_OUTPUT.PUT_LINE('工资减少');
	ELSIF :OLD.sal &lt; :NEW.sal THEN
		DBMS_OUTPUT.PUT_LINE('工资增加');
	ELSE
		DBMS_OUTPUT.PUT_LINE('工资未作任何变动');
	END IF;
	DBMS_OUTPUT.PUT_LINE('更新前工资 ：' || :OLD.sal);
	DBMS_OUTPUT.PUT_LINE('更新后工资 ：' || :NEW.sal);
END;
/
--执行UPDATE查看效果
UPDATE emp SET sal = 3000 WHERE empno = '7788';

--实例6------------------------
--创建触发器，将操作CREATE、DROP存储在log_info表
--创建表
CREATE TABLE log_info
(
	manager_user VARCHAR2(15),
	manager_date VARCHAR2(15),
	manager_type VARCHAR2(15),
	obj_name     VARCHAR2(15),
	obj_type     VARCHAR2(15)
);
--创建触发器
CREATE OR REPLACE TRIGGER trig_log_info
AFTER CREATE OR DROP ON SCHEMA
BEGIN
	INSERT INTO log_info
		VALUES(USER,SYSDATE,SYS.DICTIONARY_OBJ_NAME,SYS.DICTIONARY_OBJ_OWNER,
			SYS.DICTIONARY_OBJ_TYPE);
END;
/
--测试语句
CREATE TABLE a(id NUMBER);
CREATE TYPE aa AS OBJECT(id NUMBER);
/
DROP TABLE a;
DROP TYPE aa;
--查看效果
SELECT * FROM log_info;

--相关数据字典-----------------------------------------------------//
SELECT * FROM USER_TRIGGERS;
SELECT * FROM ALL_TRIGGERS;
SELECT * FROM DBA_TRIGGERS;  --必须以DBA身份登陆才能使用此数据字典

--启用和禁用
ALTER TRIGGER trigger_name DISABLE;
ALTER TRIGGER trigger_name ENABLE;
------------------------------------------------------------------------------------------End//
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/80436#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/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 17 May 2007 00:49:23 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/80436</link>
        <guid>http://softforce.group.javaeye.com/group/blog/80436</guid>
      </item>
      <item>
        <title>Oracle 开发 - 5</title>
        <author>javaTo</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://devezhao.javaeye.com">javaTo</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/80185" style="color:red;">http://softforce.group.javaeye.com/group/blog/80185</a>&nbsp;
          发表时间: 2007年05月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
--[5]// Oracle Procedure and Function
-------------------------------------------------------------------------------------//
--过程(PROCEDURE)--------------------------------------------------//
--创建表
CREATE TABLE user_info
(
	id   VARCHAR2(4),
	name VARCHAR2(15),
	pwd  VARCHAR2(15),
	address VARCHAR2(30)
);
--插入数据
INSERT INTO user_info VALUES('u001','zhao','zhao','shanghai');

--如要经常执行插入，Oracle每次都要进行编译，并判断语法正确性，因此执行速度可想而知，
--所以我们要创建一个过程来实现
CREATE OR REPLACE PROCEDURE AddNewUser
(
	n_id   user_info.id%TYPE,
	n_name user_info.name%TYPE,
	n_pwd  user_info.pwd%TYPE,
	n_address user_info.address%TYPE
)
AS
BEGIN
	--向表中插入数据
	INSERT INTO user_info(id,name,pwd,address)
		VALUES(n_id,n_name,n_pwd,n_address);
END AddNewUser;
/
--下面我们利用PL/SQL匿名块调用该过程
DECLARE
	--描述新用户的变量
	v_id   user_info.id%TYPE   := 'u002';
	v_name user_info.name%TYPE := 'wish';
	v_pwd  user_info.pwd%TYPE  := 'history';
	v_add  user_info.address%TYPE := 'shanghai';
BEGIN
	--调用过程，添加wish用户到数据库
	AddNewUser(v_id,v_name,v_pwd,v_add);
	DBMS_OUTPUT.PUT_LINE('用户 ' || v_name || ' 已经成功插入');
END;
/
--或者可以利用EXEC()直接插入
EXEC AddNewUser('u003','jian','jian','beijing');
--或
EXECUTE AddNewUser('u004','zhang','zhang','beijing');

--在这种上下文中，调用过程中的变量就类似于（C、VB）中的实参，而过程里的变量就是形参
--形参的模式(IN、OUT、IN OUT)，默认为IN
--IN     ：只读属性，即不能修改
--Out    ：读写属性，即可读可写
--In Out ：顾名思义，他是 IN 和 OUT 的集合
--下面通过一个示例来理解
CREATE OR REPLACE PROCEDURE ModeSimple
(
	p_InParameter    IN NUMBER,
	p_OutParameter   OUT NUMBER,
	p_InOutParameter IN OUT NUMBER
)
IS
v_LocalVariable NUMBER := 0;
BEGIN
	DBMS_OUTPUT.PUT_LINE('过程前：');
	IF (p_InParameter IS NULL) THEN
		DBMS_OUTPUT.PUT_LINE('p_InParameter is NULL');
	ELSE
		DBMS_OUTPUT.PUT_LINE('p_InParameter = ' || p_InParameter);
	END IF;
	IF (p_OutParameter IS NULL) THEN
		DBMS_OUTPUT.PUT_LINE('p_OutParameter is NULL');
	ELSE
		DBMS_OUTPUT.PUT_LINE('p_OutParameter = ' || p_OutParameter);
	END IF;
	IF (p_InOutParameter IS NULL) THEN
		DBMS_OUTPUT.PUT_LINE('p_InOutParameter is NULL');
	ELSE
		DBMS_OUTPUT.PUT_LINE('p_InOutParameter = ' || p_InOutParameter);
	END IF;
	
	--赋值
	v_LocalVariable := p_InParameter;    --合法
	v_LocalVariable := p_OutParameter;   --合法，注：必须Oracle 9i或以上版本
	v_LocalVariable := p_InOutParameter; --合法
	--!p_Inparameter := 7;  --非法，因为 IN 参数不能被修改
	p_OutParameter   := 7;  --合法
	p_InOutParameter := 8;  --合法
	
	DBMS_OUTPUT.PUT_LINE('过程末：');
	IF (p_InParameter IS NULL) THEN
		DBMS_OUTPUT.PUT_LINE('p_InParameter is NULL');
	ELSE
		DBMS_OUTPUT.PUT_LINE('p_InParameter = ' || p_InParameter);
	END IF;
	IF (p_OutParameter IS NULL) THEN
		DBMS_OUTPUT.PUT_LINE('p_OutParameter is NULL');
	ELSE
		DBMS_OUTPUT.PUT_LINE('p_OutParameter = ' || p_OutParameter);
	END IF;
	IF (p_InOutParameter IS NULL) THEN
		DBMS_OUTPUT.PUT_LINE('p_InOutParameter is NULL');
	ELSE
		DBMS_OUTPUT.PUT_LINE('p_InOutParameter = ' || p_InOutParameter);
	END IF;
END ModeSimple;
/
--利用PL/SQL匿名块调用过程来查看结果
DECLARE
	v_in  NUMBER   := 1;
	v_out NUMBER   := 2;
	v_inout NUMBER := 3;
BEGIN
	DBMS_OUTPUT.PUT_LINE('在调用过程前：');
	DBMS_OUTPUT.PUT_LINE('v_In = ' || v_in);
	DBMS_OUTPUT.PUT_LINE('v_Out = ' || v_out);
	DBMS_OUTPUT.PUT_LINE('v_InOut = ' || v_inout);
	--调用过程 ModeSimple
	ModeSimple(v_in,v_out,v_inout);
	DBMS_OUTPUT.PUT_LINE('在调用过程后：');
	DBMS_OUTPUT.PUT_LINE('v_In = ' || v_in);
	DBMS_OUTPUT.PUT_LINE('v_Out = ' || v_out);
	DBMS_OUTPUT.PUT_LINE('v_InOut = ' || v_inout);
END;
/

--与过程相关的数据字典（这里的条件必须大写）
SELECT object_name,object_type,status FROM user_objects
	WHERE object_name = 'MODESIMPLE';


--函数(Function)---------------------------------------------------//
--函数与过程结构上相似，不同的是函数有一条RETURN语句，用来返回值
--例如我们要查询用户zhao是否在user_info中存在
CREATE OR REPLACE FUNCTION CheckUser
(
	f_user user_info.name%TYPE
)
RETURN BOOLEAN  --函数返回类型
IS
v_userCount NUMBER;
BEGIN
	SELECT COUNT(name) INTO v_userCount FROM user_info WHERE name = f_user;
	IF (v_userCount > 0) THEN
		RETURN TRUE;
	ELSE
		RETURN FALSE;
	END IF;
END CheckUser;
/
--下面我们可以这样调用该函数
DECLARE
	user user_info.name%TYPE := 'jian';
	a    BOOLEAN;
BEGIN
	IF CheckUser(user) THEN
		DBMS_OUTPUT.PUT_LINE('用户 ' || user || ' 存在');
	ELSE
		DBMS_OUTPUT.PUT_LINE('用户 ' || user || ' 不存在');
	END IF;
END;
/


--附注：------------------------------------------------------------//
/* 过程与函数的差别
  函数与过程有很多相似的地方，但也有一些差别，其中的一点就是，过程的参数可以有三种模式(IN、OUT、
  IN OUT)，而函数只有一种(IN),因为使用函数的目的是传入0或多个参数，返回单一的值，想让函数返回多
  个值是一种不良的编程习惯，我们应该加以改正。
*/

/* 注意
  以上程序均未做任何错误处理（有关异常处理，请参见前面章节），但作为一种编程习惯，我们要对编写的
  程序负责，即出现异常就要处理，或在其他相应的代码中进行。
*/
----------------------------------------------------------------------------------End//
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/80185#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</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>Tue, 15 May 2007 23:17:27 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/80185</link>
        <guid>http://softforce.group.javaeye.com/group/blog/80185</guid>
      </item>
      <item>
        <title>Oracle 开发 - 4</title>
        <author>javaTo</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://devezhao.javaeye.com">javaTo</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/79108" style="color:red;">http://softforce.group.javaeye.com/group/blog/79108</a>&nbsp;
          发表时间: 2007年05月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
--[4]// Oracle Cursor and OOP Conception
-------------------------------------------------------------------------------------//
--显示游标---------------------------------------------------------//
--001
DECLARE
	CURSOR c1 IS  --声明游标
		SELECT name,address FROM student ORDER BY name;
	v_name student.name%TYPE;
	v_addr student.address%TYPE;
BEGIN
	OPEN c1;  --打开游标
	FETCH c1 INTO v_name,v_addr;  --第一次定位读取数据，并保存在变量
	--循环读取数据
	WHILE c1%FOUND LOOP
		DBMS_OUTPUT.PUT_LINE(TO_CHAR(c1%ROWCOUNT) || '  ' || v_name || ' , ' || v_addr);
		FETCH c1 INTO v_name,v_addr;
	END LOOP;
	DBMS_OUTPUT.PUT_LINE('Total rows is : ' || c1%ROWCOUNT);
	CLOSE c1;  --关闭游标
END;
/
--002
DECLARE
	CURSOR cur_emp IS
		SELECT sal FROM emp WHERE deptno = 20 FOR UPDATE OF sal;
	v_sal emp.sal%TYPE;
BEGIN
	OPEN cur_emp;
	FETCH cur_emp INTO v_sal;
	LOOP
		EXIT WHEN cur_emp%NOTFOUND;
		IF v_sal &lt; 2000 THEN
			UPDATE emp SET sal = 2000 WHERE current OF cur_emp;  --更新当前数据
		END IF;
		FETCH cur_emp INTO v_sal;
	END LOOP;
	DBMS_OUTPUT.PUT_LINE('命令执行完毕');
	
	IF cur_emp%ISOPEN THEN
		CLOSE cur_emp;
		IF cur_emp%ISOPEN THEN
			DBMS_OUTPUT.PUT_LINE('Cursor state : Open');
			CLOSE cur_emp;
		ELSE
			DBMS_OUTPUT.PUT_LINE('Cursor state : Close');
		END IF;
	END IF;
END;
/

--隐式游标---------------------------------------------------------//
--不能显式的使用OPEN、CLOSE和FETCH语句，他会自动完成
DECLARE
	no   emp.empno%TYPE;
	name emp.ename%TYPE;	
BEGIN
	SELECT empno,ename INTO no,name FROM emp WHERE empno = '7788';
	IF SQL%ISOPEN THEN
		DBMS_OUTPUT.PUT_LINE('Cursor state : Open');
	ELSE
		DBMS_OUTPUT.PUT_LINE('Cursor state : Close');
	END IF;
	DBMS_OUTPUT.PUT_LINE(no || '    ' || name);
	DBMS_OUTPUT.PUT_LINE('Return rows : ' || SQL%ROWCOUNT);
EXCEPTION
	WHEN CURSOR_ALREADY_OPEN THEN
		DBMS_OUTPUT.PUT_LINE('Cursor already open');
	WHEN NO_DATA_FOUND THEN
		DBMS_OUTPUT.PUT_LINE('No data found');
	WHEN TOO_MANY_ROWS THEN
		DBMS_OUTPUT.PUT_LINE('Return many rows');
END;
/

--游标变量（一个游标变量可以在一个PL\SQL块中使用多次）---------------------------//
DECLARE
	TYPE refcur IS REF CURSOR;  --[RETURN TYPE]
	cur_emp refcur;  --引用游标
	dept emp.deptno%TYPE;
	name emp.ename%TYPE;
BEGIN
	OPEN cur_emp FOR SELECT deptno FROM emp WHERE empno = '7788';
	FETCH cur_emp INTO dept;
	DBMS_OUTPUT.PUT_LINE('Dept : ' || dept);
	CLOSE cur_emp;

	OPEN cur_emp FOR SELECT ename FROM emp WHERE empno = '7788';
	FETCH cur_emp INTO name;
	DBMS_OUTPUT.PUT_LINE('Name : ' || name);
	CLOSE cur_emp;
END;
/

--游标在三种循环中的使用-------------------------------------------//
--001--Loop
DECLARE
	CURSOR cur_emp IS
		SELECT ename FROM emp;
	v_name emp.ename%TYPE;
BEGIN
	OPEN cur_emp;
	FETCH cur_emp INTO v_name;
	LOOP
		EXIT WHEN cur_emp%NOTFOUND;
		DBMS_OUTPUT.PUT_LINE('Name is : ' || v_name);
		FETCH cur_emp INTO v_name;
	END LOOP;
	DBMS_OUTPUT.PUT_LINE('Return rows : ' || cur_emp%ROWCOUNT);
	CLOSE cur_emp;
END;
/
--002--While
DECLARE
	CURSOR cur_emp IS
		SELECT ename FROM emp;
	v_name emp.ename%TYPE;
BEGIN
	OPEN cur_emp;
	FETCH cur_emp INTO v_name;
	WHILE cur_emp%FOUND LOOP
		DBMS_OUTPUT.PUT_LINE('Name is : ' || v_name);
		FETCH cur_emp INTO v_name;
	END LOOP;
	DBMS_OUTPUT.PUT_LINE('Return rows : ' || cur_emp%ROWCOUNT);
	CLOSE cur_emp;
END;
/
--003--For
--注：在使用 FOR 循环时，不能显式的使用 open、colse 和 FETCH 语句，他会自动完成
DECLARE
	rows number := 0;
	CURSOR cur_emp IS
		SELECT ename FROM emp;
BEGIN
	FOR v_emp in cur_emp LOOP
		DBMS_OUTPUT.PUT_LINE('name is : ' || v_emp.ename);
		rows := rows + 1;
	END LOOP;
	DBMS_OUTPUT.PUT_LINE('Return rows : ' || rows);
END;
/

--OOP Conception---------------------------------------------------//
--001
--创建对象类型（相当于C中的结构体，可实现代码重用机制）---
--**注意：OR REPLACE表示将覆盖此用户下的同名对象类型，在不熟悉数据库结构的时候不要滥用
CREATE OR REPLACE TYPE t_score AS OBJECT
(
	java number(5,2),
	net  number(5,2)
)
/
--可指定类型名称直接创建对象表
CREATE TABLE score OF t_score;
--或应用于表中
CREATE TABLE student
(
	id    VARCHAR2(4),
	name  VARCHAR2(20),
	score t_score
);
--为上表插入数据（利用构造函数）
INSERT INTO student VALUES('s101','张三',t_score(85,76));
--或
INSERT INTO student(id,name,score) VALUES('s102','李四',t_score(80,89));
--查询指定
SELECT s.score.java FROM student s;  --必须赋予别名
--002
--或者可以创建更为复杂的对象类型，即类型嵌套
CREATE OR REPLACE TYPE t_stu AS OBJECT
(
	id    VARCHAR2(4),
	name  VARCHAR2(20),
	score t_score
)
/
--应用于表中
CREATE TABLE student
(
	stu_base t_stu,
	teacher  varchar2(20)
);
--查看表结构
SET DESC DEPTH ALL;  --指定查看层次，否则只能看到第一层
DESC student;
--插入数据
INSERT INTO student
	VALUES(t_stu('s101','zhao',t_score(76,81)),'zhang');
--查询指定
SELECT s.stu_base.score.java FROM student s WHERE s.stu_base.id = 's101';

--修改对象类型（注：修改对象类型需9i以上版本）------------------------//
--其中INVALIDATE选项使得所有依赖于t_stu类型的对象和表标记为invalid
--增加属性address，注：修改后可能引起一些未知的错误，所以请不要随意修改
ALTER TYPE t_stu
	ADD ATTRIBUTE address VARCHAR2(50) INVALIDATE;

--删除类型（注：需按嵌套逐级删除）
DROP TYPE t_stu;
DROP TYPE t_score;

--继承-------------------------------------------------------------//
--创建一个不可被继承的类型
CREATE OR REPLACE TYPE super_TYPE AS OBJECT
(
	n NUMBER,
	FINAL MEMBER PROCEDURE cannot_override
)
NOT FINAL
/
--继承时将出错，可用【SHOW ERROR】语句查看错误信息
CREATE OR REPLACE TYPE sub_TYPE UNDER super_TYPE
(
	OVERRIDING MEMBER PROCEDURE cannot_override
)
/
--创建一个不可被实例化、不可被继承的类型
CREATE OR REPLACE TYPE shape AS OBJECT
(
	n NUMBER,
	NOT INSTANTIABLE MEMBER FUNCTION calculate_area RETURN NUMBER
)
NOT INSTANTIABLE NOT FINAL
/
--实例化改类型将出错
DECLARE
	l_shape shape;
BEGIN
	l_shape := shape(2);
END;
/

--嵌套表（表中之表）-------------------------------------------------//
--创建类型，（以下实例将创建一组动物饲养员嵌套表）
CREATE TYPE animal_ty AS OBJECT
(
	breed VARCHAR2(25),
	name  VARCHAR2(25),
	birthdate DATE
);
/
--此类型将用作一个嵌套表的基础类型
CREATE TYPE animal_nt AS TABLE OF animal_ty;
/
--创建嵌套表
CREATE TABLE breeder
(
	breedername VARCHAR2(25),
	animals     animal_nt
)
NESTED TABLE animals STORE AS animals_nt_tab;  --animals_nt_tab代表别名
--插入数据
INSERT INTO breeder VALUES('Mary',
	animal_nt
	(
		animal_ty('dog','butch',to_date('2004-3-31','yyyy-mm-dd')),
		animal_ty('dog','rover',to_date('2005-8-20','yyyy-mm-dd')),
		animal_ty('dog','julio',sysdate)
	)
);
INSERT INTO breeder VALUES('Jane',
	animal_nt
	(
		animal_ty('cat','an',to_date('2005-10-12','yyyy-mm-dd')),
		animal_ty('cat','jame',to_date('2002-1-23','yyyy-mm-dd')),
		animal_ty('cat','killer',to_date('2004-6-2','yyyy-mm-dd'))
	)
);
--查询表中姓名为Jane所养的动物
SELECT breed,name,birthdate
	FROM TABLE(SELECT animals FROM breeder WHERE breedername='Jane');

--可变数组（类似于嵌套表，概念上讲它是限定了行集合的嵌套表）----------//
--创建类型（以下实例将创建一组联系人嵌套表）
CREATE TYPE comm_info AS OBJECT
(
	no        NUMBER(3),    --通讯类型号
	comm_TYPE VARCHAR2(20), --通讯类型
	comm_no   VARCHAR2(30)  --号码
)
/
--创建可变数组
CREATE TYPE comm_info_list AS VARRAY(50) OF comm_info;
/
--创建表
CREATE TABLE user_info
(
	user_id   NUMBER(6),     --用户ID
	user_name VARCHAR2(20),  --用户名
	user_comm comm_info_list --与用户联系的通讯方式
);
--插入数据
INSERT INTO user_info VALUES(101,'Mary',
	comm_info_list(comm_info(1,'手机','13652369888'),
		       comm_info(2,'座机','02125689366')));
INSERT INTO user_info VALUES(102,'Tom',
	comm_info_list(comm_info(1,'手机','13765235898'),
		       comm_info(2,'座机','021-65234789')));
--查询用户ID为101的手机号码
SELECT comm_type,comm_no
	FROM TABLE(SELECT user_comm FROM user_info WHERE user_id = 101)
	WHERE no = 1;

--对象表-----------------------------------------------------------//
--创建对象
CREATE OR REPLACE TYPE address AS OBJECT
(
	id     NUMBER(4),
	street VARCHAR2(50),
	state  VARCHAR2(2),
	zip    VARCHAR2(11)
)
/
--创建对象表
CREATE TABLE address_table OF address;
--插入数据
INSERT INTO address_table 
	VALUES(1,'Oracle way','US','90001');
--或使用构造函数
INSERT INTO address_table
	VALUES(address(2,'Microsoft way','US','80863'));
--查询数据
SELECT * FROM address_table;

--VALUE关键字：以对象表别名做参数，返回对象实例
SELECT VALUE(a) FROM address_table a;

--REF数据类型：在关系表中关联对象
CREATE TABLE employee_location
(
	empno   NUMBER,
	loc_ref REF address SCOPE IS address_table  --此列引用了类型address
);
--查看结构
SET DESC DEPTH ALL;
DESC employee_location;

--REF()函数：将引用对象表中的数据插入
INSERT INTO employee_location
	SELECT 101,REF(a)
		FROM address_table a WHERE id = 1;
INSERT INTO employee_location
	SELECT 102,ref(a)
		FROM address_table a WHERE id = 2;
--查询
--注：用此语句查询的结果是未解析过的REF数据
SELECT * FROM employee_location
--DEREF()：解析REF数据，返回真正指向的实例
SELECT empno,DEREF(loc_ref)
	FROM employee_location;

--悬空REF：REF指向的对象实例被删除了，此时成为REF悬空（dangling），说明REF指向不存在的实例
DELETE FROM address_table WHERE id = 2;
--查询
--悬空的REF会返回NULL，使用 IS DANGLING 确定那些REF悬空
SELECT empno FROM employee_location
	WHERE loc_ref IS DANGLING;
--清除悬空的REF，将REF更新未NULL
UPDATE employee_location
	SET loc_ref = NULL
	WHERE loc_ref IS DANGLING;
--再查看：已经将悬空的REF清除
SELECT * FROM employee_location;

--对象视图---------------------------------------------------------//
--创建表--关系表
CREATE TABLE item
(
	item_code VARCHAR2(10),
	item_hand NUMBER(10),
	item_sode NUMBER(10)
);
--创建对象--使用相同列
CREATE OR REPLACE TYPE item_type AS OBJECT
(
	item_code VARCHAR2(10),
	item_hand NUMBER(10),
	item_sode NUMBER(10)
)
/
--建立对象视图
CREATE VIEW item_view OF item_type  --OF item_type 说明基于对象
	WITH OBJECT OID(item_code)  --WITH OBJECT OID(item_code)明确生成OID
	AS
	SELECT * FROM item
/
--我们现在可以通过视图来操作数据
INSERT INTO item_view VALUES(item_type('i101',15,50));

--MAKE_REF()
--关系主表
CREATE TABLE itemfile
(
	itemcode   VARCHAR2(5) PRIMARY KEY,
	itemdesc   VARCHAR2(20),
	p_category VARCHAR2(20),
	qty_hand   NUMBER(5),
	re_level   NUMBER(5),
	max_level  NUMBER(5),
	itemrate   NUMBER(9,2)
);
--关系从表
CREATE TABLE order_detail
(
	orderno  VARCHAR2(5),
	itemcode VARCHAR2(5),
	qty_ord  NUMBER(5),
	qty_deld NUMBER(5)
);

--PL/SQL表和记录---------------------------------------------------//
SET SERVEROUTPUT ON;
DECLARE
	TYPE rec_emp IS RECORD  --定义记录
	(
	no   emp.empno%TYPE,
	name emp.ename%TYPE
	);

	TYPE tab_emp IS TABLE OF rec_emp  --定义 PL/SQL 表
		INDEX BY binary_integer;

	i NUMBER := 1;
	temp_emp tab_emp;  --定义 PL/SQL 表的变量

	CURSOR cur_emp IS
		SELECT empno,ename FROM emp;
BEGIN
	OPEN cur_emp;
	FETCH cur_emp INTO temp_emp(i);
	LOOP
		EXIT WHEN cur_emp%NOTFOUND;
		DBMS_OUTPUT.PUT_LINE(temp_emp(i).no || '  ' || temp_emp(i).name);
		i := i + 1;
		FETCH cur_emp INTO temp_emp(i);
	END LOOP;
	DBMS_OUTPUT.PUT_LINE('总计打印了 ' || temp_emp.count || ' 条记录');

	CLOSE cur_emp;
END;
/
----------------------------------------------------------------------------------End//</pre>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/79108#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</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>Sat, 12 May 2007 19:54:35 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/79108</link>
        <guid>http://softforce.group.javaeye.com/group/blog/79108</guid>
      </item>
      <item>
        <title>Oracle 开发 - 3</title>
        <author>javaTo</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://devezhao.javaeye.com">javaTo</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/78060" style="color:red;">http://softforce.group.javaeye.com/group/blog/78060</a>&nbsp;
          发表时间: 2007年05月08日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
--[3]// Oracle PL/SQL 编程
-------------------------------------------------------------------------------------//
--创建错误信息表
CREATE TABLE ErrInfo
(
	ErrCode NUMBER(4) NOT NULL,
	ErrWord VARCHAR2(20) NOT NULL,
	ErrDate VARCHAR2(20) NOT NULL
);

--IF...ELSIF...ELSE...END IF;--------------------------------------//
DECLARE
	var1 NUMBER:=8;
BEGIN
	IF var1=1 THEN
		DBMS_OUTPUT.PUT_LINE('This NUMBER is ' || var1);
	ELSIF var1=2 THEN
		DBMS_OUTPUT.PUT_LINE('This NUMBER is ' || var1);
	ELSE
		DBMS_OUTPUT.PUT_LINE('Unknown the number');
	END IF;
END;
/
--CASE variable WHEN expression1 THEN value1;ELSE...END CASE;------//
--%ROWTYPE是指定义一个变量和数据库中某个表的一条记录数据类型一样，它指向该表的某一条记录
DECLARE 
	rec emp%ROWTYPE;
BEGIN
	SELECT  * INTO rec FROM emp WHERE ename='SCOTT';
	CASE  rec.sal
	WHEN 3000 THEN
		DBMS_OUTPUT.PUT_LINE('More than 3000');
	WHEN  2000 THEN
		DBMS_OUTPUT.PUT_LINE('More than 2000');
	ELSE
		DBMS_OUTPUT.PUT_LINE('Less than 2000');
	END CASE ;
END;
/
--LOOP...expression...EXIT WHEN expression...END LOOP--------------//
DECLARE
	var1 NUMBER:=1;
BEGIN
	LOOP
		DBMS_OUTPUT.PUT_LINE(var1);
		var1:=var1+1;
		EXIT WHEN var1=11;  --退出条件
	END LOOP;
END;
/
--WHILE...condition...LOOP...sentence...END LOOP;------------------//
DECLARE
	var1 NUMBER:=10;
BEGIN
	WHILE var1>=1  --退出条件
	LOOP
		DBMS_OUTPUT.PUT_LINE(var1);
		var1:=var1-1;
	END LOOP;
END;
/
--FOR...variable IN 1...10 LOOP...END LOOP;------------------------//
DECLARE

BEGIN
	FOR i IN 1..10 LOOP  --此条语句如变为 FOR i IN REVERSE 1..10 LOOP ，输出将为降序
		DBMS_OUTPUT.PUT_LINE(i);
 	END LOOP;
END;
/

--GOTO Label...;...;&lt;&lt;Label>>...;----------------------------------//
BEGIN
	GOTO a;  --程序将在一开始跳到标签a
	FOR i IN 1..10 LOOP
		DBMS_OUTPUT.PUT_LINE(i);
		IF i=5 THEN
			GOTO a;
		END IF;
	END LOOP;
	&lt;&lt;a>>
	DBMS_OUTPUT.PUT_LINE('This is new line');
END;
/
--嵌套实现9*9乘法表------------------------------------------------//
DECLARE
	i NUMBER:=0;
BEGIN
	WHILE i&lt;9
	LOOP
		i:=i+1;
		DECLARE
			j NUMBER:=0;
		BEGIN
			WHILE j&lt;i
			LOOP
				j:=j+1;
				DBMS_OUTPUT.PUT(j || '*' || i || '=' || i*j || ' ');
			END LOOP;
		END;
	DBMS_OUTPUT.PUT_LINE('');
	END LOOP;
END;
/

--异常处理---------------------------------------------------------//
--预定义异常
	--NO_DATA_FOUND		没有数据满足查询要求
	--ZERO_DIVIDE		算术错误，如试图用0去除一个数
	--INVALID_NUMBER	在要求数据的地方使用了非数据
	--NOT_LOGGED_ON		没有连接上Oracle
	--TOO_MANY_ROWS		SELECT INTO 返回多行记录
	--VALUE_ERROR		遇到算术的、转换的、截去的或约束错误
	--CURSOR_ALREADY_OPEN	试图打开一个已经打开的游标
	--DUP_VAL_ON_INDEX	试图插入一个已经存在的唯一约束值
	--LOGIN_DENIED		要求进入系统的请求被拒绝
	--TIMEOUT_ON_RESOURCE	等待的系统时间已经超时
	--OTHERS		其它异常

--NO_DATA_FOUND 异常-----------------------------------------------//
--%TYPE是指定义一个变量和数据库中某个表的某个字段的数据类型一样
DECLARE
	v_name emp.ename%TYPE;
BEGIN
	SELECT ename INTO v_name FROM emp WHERE empno='1234';  --异常发生，empno 中没有1234
	DBMS_OUTPUT.PUT_LINE('Name is : ' || v_name);
EXCEPTION
	WHEN NO_DATA_FOUND THEN
		DBMS_OUTPUT.PUT_LINE('No Data Found');
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/
--ZERO_DIVIDE 异常-------------------------------------------------//
BEGIN
	DBMS_OUTPUT.PUT_LINE(5/0);  --异常发生，不能被0除
EXCEPTION
	WHEN ZERO_DIVIDE THEN
		DBMS_OUTPUT.PUT_LINE('Can not divide zero');
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/
--TOO_MANY_ROWS 异常-----------------------------------------------//
DECLARE
	no emp.empno%TYPE;
	name emp.ename%TYPE;
	dept emp.deptno%TYPE;
BEGIN
	SELECT empno,ename,deptno INTO no,name,dept FROM emp WHERE empno = 7369;
	DBMS_OUTPUT.PUT_LINE('员工号 ：' || no);
	DBMS_OUTPUT.PUT_LINE('员工名 ：' || name);
	DBMS_OUTPUT.PUT_LINE('部门号 ：' || dept);
EXCEPTION
	WHEN NO_DATA_FOUND THEN
		DBMS_OUTPUT.PUT_LINE('7369雇员不存在');  --未找到数据
	WHEN TOO_MANY_ROWS THEN
		DBMS_OUTPUT.PUT_LINE('有多个学员号是7369');  --返回多行
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/
--DUP_VAL_ON_INDEX 异常--------------------------------------------//
BEGIN
	INSERT INTO emp
	VALUES('7788','LaoZhao','Soft','7689','03-12月-81','2600','0','20');
EXCEPTION
	WHEN DUP_VAL_ON_INDEX THEN
		DBMS_OUTPUT.PUT_LINE('违反了PRIMARY KEY约束：7788雇员已经存在');
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/
-------------------------------------------------------------------//
--如果员工7788的工资小于3000，则更新为3000，如未找到该雇员，则利用异常处理打印相应信息
DECLARE
	salary emp.sal%TYPE;
BEGIN
	SELECT sal INTO salary FROM emp WHERE empno='7788';
	IF salary &lt; 3000 THEN
		UPDATE emp SET sal = '3000' WHERE empno = '7788';
		DBMS_OUTPUT.PUT_LINE('记录已更新');
	ELSE
		DBMS_OUTPUT.PUT_LINE('IF 条件不成立');
	END IF;
EXCEPTION
	WHEN NO_DATA_FOUND THEN
		DBMS_OUTPUT.PUT_LINE('7788雇员不存在');
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/

--用户自定义异常---------------------------------------------------//
--001
DECLARE
	--v_num1 NUMBER:=5;
	v_num1 NUMBER:=0;
	--v_num2 NUMBER:=0;
	v_num2 NUMBER:=5;
	MyException EXCEPTION;
BEGIN
	DBMS_OUTPUT.PUT_LINE(v_num1/v_num2);	
		RAISE MyException;  --引发自定义异常
	
	DBMS_OUTPUT.PUT_LINE('OK');  --此句永远不会执行，因为发生异常后程序将直接跳到EXCEPTION段
EXCEPTION
	WHEN MyException THEN
		DBMS_OUTPUT.PUT_LINE('Cannot Divide Zero');
	--WHEN ZERO_DIVIDE THEN
	--	DBMS_OUTPUT.PUT_LINE('Can not Divide Zero');
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/
--002
DECLARE
	id score.id%TYPE;
	java score.java%TYPE;
	MyException EXCEPTION;
BEGIN
	SELECT id,java INTO id,java FROM score WHERE id = 4;
	IF java &lt; 0 OR java > 100 THEN
		RAISE MyException;
	ELSE
		DBMS_OUTPUT.PUT_LINE('OK');
	END IF;

EXCEPTION
	WHEN MyException THEN
		UPDATE score SET java=0 WHERE id = 4;
		DBMS_OUTPUT.PUT_LINE('分数不能大于100或小于0，现已经清0');
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/
--003
DECLARE
	v_date emp.hiredate%TYPE;
	MyException EXCEPTION;
BEGIN
	INSERT INTO emp(empno,hiredate)
		VALUES(1111,TO_DATE('2010-12-25','yyyy-mm-dd'));
	COMMIT;
	SELECT hiredate INTO v_date FROM emp WHERE empno=1111;
	IF v_date > SYSDATE THEN
		RAISE MyException;
	END IF;
	DBMS_OUTPUT.PUT_LINE('执行完毕');
EXCEPTION
	WHEN MyException THEN
		DBMS_OUTPUT.PUT_LINE('雇用日期不能大于当前日期');
		--raise_application_error(-20002,'雇用日期不能大于当前日期');
		UPDATE emp SET hiredate = SYSDATE WHERE empno = 1111;
		DBMS_OUTPUT.PUT_LINE('日期已更新为当前日期');
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/

--将定义好的异常与标准的ORACLE错误联系起来-------------------------//
--001
DECLARE
	MyException EXCEPTION;
	PRAGMA EXCEPTION_INIT(MyException,-00001);  --关联语句
BEGIN
	INSERT INTO emp(empno) VALUES(1234);  --发生异常，企图插入有Check约束的重复值
	COMMIT;  --插入后提交
	DBMS_OUTPUT.PUT_LINE('插入正常');
EXCEPTION
	WHEN MyException THEN
		DBMS_OUTPUT.PUT_LINE('ORA-00001: 违反了唯一约束');
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/
--002
CREATE TABLE a
(
	id INT NOT NULL,
	name VARCHAR2(20) NOT NULL
);
DECLARE
	MyException EXCEPTION;
	PRAGMA EXCEPTION_INIT(MyException,-1400);  --关联语句
BEGIN
	INSERT INTO a(id) VALUES(1);  --发生异常，违反了NOT NULL约束
EXCEPTION
	WHEN MyException THEN
		DBMS_OUTPUT.PUT_LINE('错误代号：-1400');
		DBMS_OUTPUT.PUT_LINE('错误描述：违反了NOT NULL约束');
		DBMS_OUTPUT.PUT_LINE('错误发生时间：' || 
					TO_CHAR(SYSDATE,'yyyy-mm-dd hh24:mi:ss'));
		INSERT INTO errinfo 
	  	  VALUES('-1400','违反了 NOT NULL约束',TO_CHAR(SYSDATE,'yyyy-mm-dd hh24:mi:ss'));
		DBMS_OUTPUT.PUT_LINE('已经将错误记录在ErrInfo表');
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/
--003
DECLARE
	MyException EXCEPTION;
	salary emp.sal%TYPE;
BEGIN
	SELECT sal INTO salary FROM emp WHERE empno = '7788';
	IF salary > 2000 THEN
		RAISE MyException;
	END IF;
EXCEPTION
	WHEN MyException THEN
		RAISE_APPLICATION_ERROR(-20001,'RAISE_APPLICATION_ERROR异常发生',FALSE); --TRUE
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/
--课后练习---------------------------------------------------------//
--001
DECLARE
	gz emp.sal%TYPE;
	MyExc EXCEPTION;
BEGIN
	SELECT sal INTO gz FROM emp WHERE ename='SCOTT';
	DBMS_OUTPUT.PUT_LINE('原工资 : ' || gz);
	IF gz &lt; 2000 THEN
		RAISE MyExc;
	ELSE
		DBMS_OUTPUT.PUT_LINE('工资无需更新');
	END IF;
EXCEPTION
	WHEN MyExc THEN
		UPDATE emp SET sal = 3000 WHERE ename='SCOTT';
		DBMS_OUTPUT.PUT_LINE('记录已经更新');
		SELECT sal INTO gz FROM emp WHERE ename='SCOTT';
		DBMS_OUTPUT.PUT_LINE('更新后工资 : ' || gz);
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/
--002
DECLARE
	lo salgrade.losal%TYPE;
	hi salgrade.hisal%TYPE;
	MyExc EXCEPTION;
BEGIN
	INSERT INTO salgrade VALUES(6,2600,2400);
	COMMIT;
	SELECT losal,hisal INTO lo,hi FROM salgrade WHERE grade = 6;
	IF lo > hi THEN
		RAISE MyExc;
	ELSE
		DBMS_OUTPUT.PUT_LINE('记录已经插入');
	END IF;
EXCEPTION
	WHEN MyExc THEN
		--删除插入的记录并打印相应信息
		delete salgrade WHERE grade = 6;
		DBMS_OUTPUT.PUT_LINE('记录插入失败 LOSAL 必须小于 HISAL');
	WHEN OTHERS THEN
		DBMS_OUTPUT.PUT_LINE('Unknown Error');
END;
/

--附注-------------------------------------------------------------//
--如需在PL\SQL中进行值输入，
DECLARE
  num LONG;
BEGIN
  num := '&num';
  DBMS_OUTPUT.PUT_LINE('Input value is : ' || num);
END;
/
--注意：如果要使你在DBMS_OUTPUT.PUT_LINE(...)中显示的语句得以显示，则必须显示的调用
SET SERVEROUTPUT ON;
----------------------------------------------------------------------------------End//


</pre>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/78060#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><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><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 08 May 2007 23:37:54 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/78060</link>
        <guid>http://softforce.group.javaeye.com/group/blog/78060</guid>
      </item>
      <item>
        <title>Oracle 开发 - 2</title>
        <author>javaTo</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://devezhao.javaeye.com">javaTo</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/76615" style="color:red;">http://softforce.group.javaeye.com/group/blog/76615</a>&nbsp;
          发表时间: 2007年05月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <pre name="code" class="java">
--[2]// Oracle Basic 2
-------------------------------------------------------------------------------------//
--用户-------------------------------------------------------------//
--（注：一定要以DBA身份的用户登陆才能完成下列操作）
--查看数据库已有的用户信息
SELECT * FROM DBA_USERS;

--创建新用户（用户名：laozhao ，密码：laozhao）
CREATE USER laozhao IDENTIFIED BY laozhao;
--删除用户
DROP USER laozhao;
--用户授权（赋予CONNECT,RESOURCE角色），不授权，用户将不可用
GRANT CONNECT,RESOURCE TO laozhao;

--角色-------------------------------------------------------------//
--（注：一定要以DBA身份的用户登陆才能完成下列操作）
--查看数据库已有角色
SELECT * FROM DBA_ROLES;

--创建角色
CREATE ROLES role_name;
--删除角色
DROP ROLES role_name;
--为新建角色赋予已有的角色权限
GRANT CONNECT TO role_name;
--为新建角色赋予student表的SELECT权限
GRANT SELECT ON student TO role_name;

--权限-------------------------------------------------------------//
--查询所有系统权限
SELECT PRIVILEGE FROM DBA_SYS_PRIVS;

--查看当前用户的系统权限
SELECT * FROM USER_SYS_PRIVS;
--查看当前用户的对象权限
SELECT * FROM USER_TAB_PRIVS;

--锁---------------------------------------------------------------//
--表一旦锁住，别的用户将不可有（增、删、改）操作
--表级共享锁（多用户可以放置）
LOCK TABLE emp IN SHARE MODE;
--表级排它锁（单个用户放置）
LOCK TABLE emp IN EXCLUSIVE MODE;
--行锁
--在执行DML语句时，Oracle会自动为执行行添加行级锁

--创建表-----------------------------------------------------------//
--下面一张学院资料表，一张得分表
--表1
CREATE TABLE student
(
 id NUMBER,
 name VARCHAR2(20),
 sex VARCHAR2(3),
 age NUMBER,
 address VARCHAR2(50),
 CONSTRAINT student_pk PRIMARY KEY(id)   --主键约束
);
--或创建后修改表格
--ALTER TABLE students ADD CONSTRAINT student_pk PRIMARY KEY(id);
--表2
CREATE TABLE score
(
 id NUMBER,	
 clanguage NUMBER(5,2),  --共五位数字，小数点占用两位
 java      NUMBER(5,2),
 vb        NUMBER(5,2),
 asp       NUMBER(5,2),
 CONSTRAINT score_fk FOREIGN KEY(id) REFERENCES student(id)  --外键约束
);

--为上面创建的表插入数据
INSERT INTO student
	VALUES('2','JianLi','F','20','ShangHaiShi YangPu');
INSERT INTO score
	VALUES('2','87','79','92','99');
--也可为指定列插入
INSERT INTO student(id,address)
	VALUES('1','AnHui SuZhou');

--删除表内指定数据
DELETE student WHERE id=1;
--删除表
DROP TABLE student;

--查询语句(查询所有)
SELECT * FROM student
--查询语句(查询指定列)
SELECT id,address FROM student;
--可指定“用户名.表名”查询，如想查询scott用户下的emp表，可写为（注：权限低的用户查询不到权限高的用户表）
SELECT * FROM scott.emp;

--序列-------------------------------------------------------------//
--创建序列(创建名为stu_id的序列)
CREATE SEQUENCE stu_id
INCREMENT BY 1   --对上一数字的增量(可为负数)
START WITH 1     --序列起始值
NOMAXVALUE       --指定序列最大值，或无最大值(设置最大值只需去除no，并在其后加入最大值即可)
NOMINVALUE       --指定序列最小值，或无最小值
NOCYCLE          --指定到达最大或最小值时是否循环处理
ORDER            --保证产生的序列是按照一定的顺序(不保证可在前加入no，默认为NOORDER)
CACHE 10;        --指定在内存中可使用的序列个数，(当内存中序列用完时再生成下一批序列放入内存，以提高效率)

--查询内存中剩余的序列
SELECT stu_id.NEXTVAL FROM student;
--使用序列(NEXTVAL,CURRVAL)
--插入数据时(NEXTVAL)
INSERT INTO student(id,address)
	VALUES(stu_id.NEXTVAL,'AnHui SuZhou');
--使用当前值(CURRVAL)
INSERT INTO student(id,name)
	VALUES(stu_id.CURRVAL,'zhao');

--删除序列
DROP SEQUENCE stu_id;

--同义词-----------------------------------------------------------//
--创建同义词(公有),创建了student 的同义词 stu
CREATE PUBLIC SYNONYM stu FOR student;
--创建同义词(私有)
CREATE SYNONYM stu FOR student;

--删除同义词(注：删除时要指定公有还是私有)
DROP PUBLIC SYNONYM stu;
/*
  可把同义词(SYNONYM)或表(TABLE)、视图(VIEW)、快照(SNAPSHOT)、序列(SEQUENCE)、过程(PROCEDURE)、
  函数(FUNCTION)、包(PACKAGE)、对象类型(OBJECT TYPE)等从别的用户那里引用过来创建属于自己的，
  如：要引用system用户的stu同义词（注：权限低的用户不能操作权限高的用户）
*/
CREATE SYNONYM stu FOR system.stu;

--视图-------------------------------------------------------------//
--创建一个简单的视图
CREATE VIEW stu_info
	AS
	SELECT id,name FROM student;

--创建一个拥有两张（上述：Student、scort）表的视图
CREATE VIEW stu_Java
	AS
	SELECT student.id,name,java FROM student,score
	WHERE student.id = score.id;  --视图连接条件，必选

--删除试图
DROP VIEW stu_info;

--索引-------------------------------------------------------------//
--创建示例表
CREATE TABLE students
(
	id NUMBER,
	name VARCHAR2(20),
	sex CHAR(1),
	age NUMBER
);
--BTree索引
CREATE INDEX ind_id ON students(id);
--位图索引
CREATE BITMAP INDEX ind_sex ON students(sex);
--反向键索引
CREATE INDEX ind_age ON students(age) REVERSE;
--函数索引
CREATE INDEX ind_name ON students(lower(name));

--查看所创建的索引信息
SELECT index_name,index_type FROM USER_INDEXES WHERE table_name='STUDENTS';

--删除索引
DROP INDEX ind_id;

--附注-------------------------------------------------------------//
--创建概要（配置）文件
CREATE PROFILE
	appl_profile
LIMIT
	SESSIONS_PER_USER               2  --
	CPU_PER_SESSION             10000  --hunderth of seconds
	CPU_PER_CALL                    1  --hunderth of seconds
	CONNECT_TIME            UNLIMITED  --minutes
	IDLE_TIME                      30  --minutes
	LOGICAL_READS_PER_SESSION DEFAULT  --db bLOCKs
	LOGICAL_READS_PER_CALL    DEFAULT  --db bLOCKs
	PRIVATE_SGA                   20M  --
	FAILED_LOGIN_ATTEMPTS           3  --
	PASSWORD_LIFE_TIME             30  --days
	PASSWORD_REUSE_TIME            12  --days
	PASSWORD_REUSE_MAX      UNLIMITED  --
	PASSWORD_LOCK_TIME        DEFAULT  --days
	PASSWORD_GRACE_TIME             2  --days
	PASSWORD_VERIFY_FUNCTION     NULL  --
/

--修改概要（配置）文件
ALTER PROFILE appl_profile LIMIT
	CPU_PER_CALL DEFAULT;
--删除概要（配置）文件
DROP PROFILE appl_profile;
--如要删除的概要（配置）文件已经分配给用户，则必须利用下面语句进行删除
DROP PROFILE appl_profile CASCADE;

--在创建用户时可以指定概要（配置）文件，如不指定，则使用默认概要（配置）文件
CREATE USER zhao IDENTIFIED BY zhao PROFILE appl_profile;
--如需要改变用户的概要（配置）文件
ALTER USER user_name PROFILE perfile_name;

--DBA用户可以修改默认概要（配置）文件，但任何用户都不能删除概要（配置）文件
ALTER PROFILE DEFAULT LIMIT CPU_PER_CALL 2;
----------------------------------------------------------------------------------End//
</pre>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/76615#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><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><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 02 May 2007 10:15:03 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/76615</link>
        <guid>http://softforce.group.javaeye.com/group/blog/76615</guid>
      </item>
      <item>
        <title>对Java EE的十大不当使用导致的性能问题</title>
        <author>viwo</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://viwo.javaeye.com">viwo</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/76470" style="color:red;">http://softforce.group.javaeye.com/group/blog/76470</a>&nbsp;
          发表时间: 2007年05月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font face="Arial">Vincent Partington近两个半月来在他的博客上陆续发表了关注Java EE平台性能问题的文章</font></p>
<p>即对<font face="Arial">Java EE的十大不当使用导致的性能问题</font></p>
<p><font face="Arial">#10 - <a href="http://blog.xebia.com/2007/02/18/ejapp-top-10-countdown-10-excessive-logging/" target="Excessive logging">Excessive logging</a><br />
#9 - <a href="http://blog.xebia.com/2007/02/25/ejapp-top-10-countdown-9-incorrect-application-server-configuration/">Incorrect application server configuration<br />
</a>#8 - <a href="http://blog.xebia.com/2007/03/09/ejapp-top-10-countdown-8-incorrect-usage-of-java-ee/">Incorrect usage of Java EE<br />
</a>#7 - <a href="http://blog.xebia.com/2007/03/19/ejapp-top-10-countdown-7-unnecessary-use-of-xml/">Unnecessary use of XML</a><br />
#6 - <a href="http://blog.xebia.com/2007/03/26/ejapp-top-10-countdown-6-improper-caching/">Improper caching<br />
</a>#5 - <a href="http://blog.xebia.com/2007/04/02/ejapp-top-10-countdown-5-excessive-memory-usage/">Excessive memory usage<br />
</a>#4 - <a href="http://blog.xebia.com/2007/04/16/ejapp-top-10-countdown-4-badly-performing-libraries/">Badly performing libraries<br />
</a>#3 - <a href="http://blog.xebia.com/2007/04/22/ejapp-top-10-countdown-3-incorrectly-implemented-concurrency/">Incorrectly implemented concurrency<br />
</a>#2 - <a href="http://blog.xebia.com/2007/04/25/ejapp-top-10-countdown-2-unnecessary-remoting/">Unnecessary remoting</a><br />
#1 - <a href="http://blog.xebia.com/2007/04/29/ejapp-top-10-countdown-1-incorrect-database-usage/">Incorrect database usage</a></font></p>
<p>最后一篇中作者给出了一些建议：</p>
<p>1&nbsp; Java开发人员应该始终关注应用程序的性能问题。</p>
<p>2&nbsp; Java开发人员应该同能够帮助他提高应用程序性能的人如DBA一起工作。</p>
<p>3&nbsp; 最后作者推荐了一个Java性能调优网站 <font face="Arial"><a href="http://www.javaperformancetuning.com/tips/index.shtml">Java Performance Tuning</a>&nbsp;。</font></p>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/76470#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 01 May 2007 10:05:34 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/76470</link>
        <guid>http://softforce.group.javaeye.com/group/blog/76470</guid>
      </item>
      <item>
        <title>Oracle 开发 - 1</title>
        <author>javaTo</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://devezhao.javaeye.com">javaTo</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/71608" style="color:red;">http://softforce.group.javaeye.com/group/blog/71608</a>&nbsp;
          发表时间: 2007年04月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          总结了一些Oracle的代码，看看对大家有没有帮助，如果哪里错了，请帮忙指正，后面的一些会陆续发表上来。<br /><br /><pre name="code" class="java">
-- 默认系统系统管理员
-- system/manager,  sys/change_on_install  以SYSDBA登陆
-- 普通用户
-- scott/tiger 以NORMAL登陆

[1]// Oracle Basic 1
-------------------------------------------------------------------------------------//
--可在登陆时转换登陆身份(转换为system登陆)
CONNECT system/Manager

--回滚事务（返回上一次操作）
--ROLLBACK;

--提交事务
COMMIT;

--查看表结构
DESC table_name;

--查询表中数据
SELECT * FROM table_name;
--或指定需返回的字段
SELECT id,name FROM table_name;

--显示当前用户
SHOW USER;

--查看当前用户所拥有的表的结构
DESC USER_TABLES;
--查看当前用户所拥有的表
SELECT table_name FROM USER_TABLES;

--查看当前用户能够访问的表的结构
DESC ALL_TABLES;
--查看当前用户能够访问的表
SELECT table_name FROM ALL_TABLES;

--查看整个数据库所拥有的表的结构
DESC DBA_TABLES;
--查看整个数据库所拥有的表
SELECT table_name FROM DBA_TABLES;

--查看数据库版本
SELECT * FROM V$VERSION;

--查看数据库实例名称
SELECT instance_name FROM V$INSTANCE;

--查看数据文件的物理位置
SELECT * FROM V$DATAFILE;

--查看日志文件的物理位置
SELECT * FROM V$LOGFILE;

--查看控制文件的物理位置
SELECT * FROM V$CONTROLFILE;

--查看表空间的信息
SELECT * FROM V$TABLESPACE;

--查看数据库参数信息
--下面列出几种参数
--简单查询方法
SHOW PARAMETER DB_BLOCK_SIZE;
SHOW PARAMETER NLS_LANGUAGE;
SHOW PARAMETER JAVA_POOL_SIZE;
SHOW PARAMETER SORT_AREA_SIZE;
--通过视图查询
SELECT * FROM V$PARAMETER WHERE NAME='JAVA_POOL_SIZE';
SELECT name,value FROM V$PARAMETER WHERE NAME='JAVA_POOL_SIZE';
--修改参数值
--!UPDATE V$PARAMETER SET VALUE='500000' WHERE name='JAVA_POOL_SIZE';

--附注-------------------------------------------------------------//
SPOOL d:\file.txt;    --联机
SPOOL OFF;            --关闭（将联机后查询到的数据保存在d盘file.txt文件下）

--命令方式打开和关闭数据库
--以sysdba身份登陆数据库
CONNECT /AS SYSDBA;
--关闭数据库
SHUTDOW IMMEDIATE;
--启动数据库
STARTUP;

--清除屏幕
CLEAR SCREEN;

--预定义格式打印系统当前日期
SELECT TO_CHAR(sysdate,'yyyy-mm-dd hh24:mi:ss') FROM DUAL;

--可以利用脚本执行SQL语句（d:\test.sql）
@d:\test.sql;

--编辑当前SQL语句
EDIT;
--或
ED;

--保存当前SQL语句
SAVE d:\test.sql;

--退出数据库
EXIT;
--或
QUIT;
----------------------------------------------------------------------------------End//

</pre>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/71608#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/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 16 Apr 2007 23:33:41 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/71608</link>
        <guid>http://softforce.group.javaeye.com/group/blog/71608</guid>
      </item>
      <item>
        <title>Ajax的思考</title>
        <author>viwo</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://viwo.javaeye.com">viwo</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/69324" style="color:red;">http://softforce.group.javaeye.com/group/blog/69324</a>&nbsp;
          发表时间: 2007年04月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><font face="Arial">Ajax被各种媒体宣传的太过火暴，抛开众多的宣传泡沫，我们来认真的思考一下，Ajax到底是什么？它能用来干什么？它应该用来干什么？<br />
Ajax是Asynchronous JavaScript and XML的缩写，其中有三个关键词：<br />
1 Asynchronous <br />
2 JavaScript <br />
3 XML<br />
这三个关键词可以这么理解：<br />
1 交互是异步的<br />
2 在客户端用JavaScript接收、发送、展示数据<br />
3 用XML作为传输介质<br />
(注：严谨的说1，2，3都不一定，这里只考虑一般的状况)<br />
那么这种性质的Ajax能用来做些什么呢？</font></p>
<p><font face="Arial">可以用这么一段话来描述一下它的作用：<br />
页面中的某个事件（点击、选择等）被JavaScript代码捕捉到，JavaScript对事件涉及到的数据进行封装，封装完成后以XML形式发送到服务器端，服务器端根据所给数据执行相应的查询处理封装出一份结果返回给客户端，客户端JavaScript接收到返回结果后解析并展现在客户端。</font></p>
<p><font face="Arial">如果你理解了这段话，那么你应该会发现这和我们传统的&ldquo;页面提交模型&rdquo;很像。</font></p>
<p><font face="Arial">差别其实就是这个Asynchronous，也就是说客户端数据封装后的发送是异步执行的，通俗一点讲就是：客户端向服务器端发送请求数据后，客户端这边该干什么还干什么，你看不出什么变化。当结果从服务器端返回后，客户端JavaScript得到结果，神不知鬼不觉的把结果放在页面的某个地方。</font></p>
<p><font face="Arial">这样你说Ajax能用来干什么？可以说传统的&ldquo;页面提交模型&rdquo;能干的事情它都能干。<br />
但是它能干未必就意味着我们就要这么干。试想，用户注册页面用Ajax实现会是怎么个场景？</font></p>
<p><font face="Arial">最后，它应该用来干什么？<br />
1 二级或N级联动列表<br />
如果下一级列表数据依赖于上一级选择，并且数据是动态不定的，那么这种情况用Ajax实现就会很自然。<br />
2 用户界面输入辅助<br />
你在Google中输入一个或几个字，就会出现一个下拉列表供你选择比较热门的相关词语。<br />
3 数据校验<br />
当焦点离开某控件时判断控件中数据是否合法。</font></p>
<p><font face="Arial">以上三种情况是我认为比较适合使用Ajax的代表。当然Ajax还有更多的应用，不过从上面我们&ldquo;可见一斑&rdquo;。</font></p>
<p><font face="Arial">基于上述各点，我认为Ajax能为Web程序添加很多光彩，但是想要颠覆甚至取代传统Web编程模型，那是不可能完成的任务。</font></p>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/69324#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/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 09 Apr 2007 18:22:00 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/69324</link>
        <guid>http://softforce.group.javaeye.com/group/blog/69324</guid>
      </item>
      <item>
        <title>转过来 ，非常好 的 关于 J2EE</title>
        <author>piaochunzhi</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://piaochunzhi.javaeye.com">piaochunzhi</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/59494" style="color:red;">http://softforce.group.javaeye.com/group/blog/59494</a>&nbsp;
          发表时间: 2007年03月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>1.我们谈论了J2EE，但究竟什么是J2EE？它是规范吗？它是技术吗？它是在什么样的背景下出现的，为了解决什么？<br />
2.我们也谈架构？但究竟什么是架构？架构出于什么目的？架构的目标是什么呢？<br />
3.我们频繁的使用Struts,但它帮我们解决什么呢？可能有人会说它是MVC的实现，但这不是问题的答案.MVC它又解决了什么呢？</p>
<p>&nbsp;</p>
<p><span class="tpc_content">1. J2EE是规范，是一种JSR标准，有详细文档，阐述J2EE提供哪些功能，可以下载这样文档，当然还有一些代码接口，这是典型Java世界中的框架代码+标准文档形式，这是只有自由世界才有的规范，在微软MS世界你是绝对不会看到的，所以，从微软转过来的，会晕，会不适应，不能再按照他们以前的经验来看待自由的新世界。<br />
<br />
2.架构是就软件平台的搭建和设计规划，目的是实现软件最大的可维护性和可拓展性，延续软件的生命，就象人生下来，整个架构都有了，虽然一些器官不能用到（例如生殖器官），但是一生下来还是有这些器官，这就是架构设计的优势，没有架构设计的软件是看不到明天，生下的小孩就不会有生殖器官，因为他认为小孩不需要，但是他没有看到小孩20岁以后的未来。<br />
<br />
架构就是要有预见性，特别是Java世界，技术流派众多，优劣共存，让人吃药的技术比比皆是，不象微软世界，有微软这个专制强权的架构设计者和提供者告诉你用什么，除此之外别无选择，在Java自由世界，你可能不小心走上一个不归路，软件架构一旦错误，就象出发的方向发生问题，南辕北辙成语就是说这个意思，花再多精力再多钱，再强的人都没有用，项目照样失败。<br />
<br />
所以，在Java世界选择技术，就象女孩子到自由市场淘货，必须冒被骗失败的风险，但是其中乐趣也是不言而喻的，你会成为技术专家，当然，如果你想很多找到合适的架构设计，那么借助外力，象J道都提供这样架构设计服务，可以在短时间介绍一些这个自由市场哪些东西是性价比好，值得买，找个有信誉的内行当地人做咨询，就是这个道理。<br />
<br />
目前Java世界，架构设计主要是框架选择，如果你的团队非常弱，可能只会基础的Java编程，那么选择强制性框架就比较好，这样可以在保证软件质量情况下，不让不太懂的人胡作非为，破坏软件整体的可维护性，好的框架甚至只需要XML配置就可以，这样，OO能力差一些人，就不需编程代码，配置配置XML就可以，这样，通过架构设计，可以充分发挥现有人员的长处，克服他们的短处。<br />
<br />
所以，为什么过去数据库专家DBA年薪20万，而现在架构师年薪20万。而且DBA年薪20万已经成为过去时，因为人们已经发现，再好的数据库设计，只是数据库设计，不是程序语言设计，更多维护烦琐和复杂工作我们是需要修改的程序代码，所以，大家才开始重视应用程序代码，并且发现程序代码控制比数据库设计更难控制，所以有了OO体系专门对付程序代码，进而有了框架，从而诞生比DBA更重要的architect了。<br />
<br />
3.关于struts重要性，还是必须从程序代码可维护性来讲，也就是从OO角度讲，Struts能够通过MVC模式将表现层进行细分，实现表现层内部各个细分部分的最大解耦，然后，Struts也可以将页面离散无规律的数据转变为对象，供业务层服务，也就是Struts表现层实际是业务层的服务者，为其提供对象化的枪支弹药，而业务层则可以围绕这些对象实现对象化编程，从而实现更好的可维护性，Evans DDD对业务层进行细分，这些都是基于对象基础，当然持久层不用说，和表现层一样也是业务层的服务者，为其提供对象化的枪支弹药，不过这些对象是从数据库里拿来的，是从一个非对象化，离散的、关系型的数据库拿来的，Hibernate等框架必须将他们转为对象，给业务层使用。<br />
<br />
所有这些框架，都是保证我们业务逻辑完全OO，这个前提是：你相信只有OO才是目前实现软件最大维护性和拓展性的适当方式，虽然可能不是最好的，但他是目前最合适的，否则全世界软件工业不会花这么多力气在OO上了。<br />
<br />
因为我们国内将软件看成数学，软件论文实际是数学公式论文，可以发生了软件研究方向的偏离，没有走上OO正确研究方向，这样导致很多程序员学校毕业后，根本没有OO基本意识，甚至有人抵触OO，我从出版社内部销售资料看到：Foxpro等数据库书籍名列销售前列，我是欲哭无泪，中国人的软件误区中还要走多少年。<br />
<br />
所有这些，必须从我们教育体系寻找，这里面话题太多，我想其中一个问题还是：中微软毒太深，因为微软已经帮你做了架构的事情，你唯一要做的就是拿来某个软件，按照其说明书做，但是为什么这么做，几乎没有人去研究。<br />
<br />
长此以往，很多人就根本没有了去探索的想法，安之罗素了，然后开始研究数学了，认为数学越奥深，软件就好，数学只是算软件服务的众多专业领域的一个领域，软件可以服务于管理专业、物流专业、银行专业、财会专业等等，软件可以服务这么多领域专业，那么软件本身应该如何做才是专业的呢？就是软件的可维护性和可拓展性，你必须活得够长，为你的主人服务，如果你一开始没有生殖器官，那么20岁以后你不是没用了，人就此绝种了？<br />
<br />
软件绝种就是重新开发一套新的系统，这样做，对它所服务对象的杀伤力是很大的，国外大型企业信息主管已经深有体会：硬件落后了，我可以花更多钱替换，但是软件不能彻底替换，只能在其原来基础上延伸，但是如果发现这个软件不能延伸，就是请bill gates来，也没有用，那么这种损失是无以伦比，不能用金钱衡量的，这就是软件架构失败带来的损失。<br />
<br />
因为我们国家长期来都是国有经济，能够活上百年的民营企业不多，国有银行等大型企业因为开始就请外国人做咨询，虽然也有彻底换软件的痛苦，但是有强有力国外厂商这些过来知道，弯路就是有不会太大。很多大型企业也是近期才上MRP或者ERP，民营企业基本都靠低廉的劳动力存活，不是靠管理，所以软件对于他们没有起到重要作用，所以，因为软件架构问题暴露的社会问题不会大规模出现，但是，如果不重视，迟早会出现。<br />
<br />
我本人因为做得比较早，经历过因为不注重软件架构，导致方向错误，最后项目失败了才明白得经历。所以希望通过J道这样地方，呼吁更多人重视架构。<br />
<br />
但是，现在又有一种现象：有些人嘴上架构框架很熟悉，但是实现起来代码还是乱糟糟，根本不是OO，这就象练武功的人，如果不经过有经验老师的点拨，靠自己看书，就会十分业余，具体表现就是嘴上功夫行，实际做起来不行，也就是他没有将理论和实践联系起来，就差这个窗户玻璃纸捅破，需要别人帮助，所以我提供培训咨询服务，没有教授高深知识，就是帮助你捅破窗户纸，但是，靠自己，什么时候能通，说不定呢，项目不等人，当然经常来Jdon论坛也可以看到大家这方面讨论。<br />
<br />
说太多，有感而发，个人意见，仅供参考。<br />
</span></p>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/59494#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><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 13 Mar 2007 09:04:17 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/59494</link>
        <guid>http://softforce.group.javaeye.com/group/blog/59494</guid>
      </item>
      <item>
        <title>死去 死去</title>
        <author>basicbest</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://basicbest.javaeye.com">basicbest</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/56986" style="color:red;">http://softforce.group.javaeye.com/group/blog/56986</a>&nbsp;
          发表时间: 2007年03月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div>死去<br />
...<br />
<br />
可测试性是判断框架是否良好的一个重要标准，特别是现在......</div>
<div>逻辑结构上的清晰，必然会在性能上造成损失(沟通成本高)，但是，后期的可维护性，和扩展能力，也都是必须要考虑的。又是一个掌握平衡的事情。</div>
<div>现在随便拉一个程序员过来，他都能说出MVC是什么，却始终无法领会到其背后的本质。资讯网络的发达，造就了大批浮躁的人，可能我也是一个。</div>
<div>知识--&gt;理解--&gt;意识--&gt;悟性，如果<a href="http://www.intsci.ac.cn/research/cognitive.html">认知过程</a>是这个样子，那么，我现在对世界的认识所处的位置在哪里？</div>
<div><a href="http://zh.wikipedia.org/wiki/%E6%95%B0%E5%AD%A6%E6%A8%A1%E5%9E%8B">数学模型</a>是近似的，但数学过程是精确的。很奇怪的事情。宇宙中每个个体都有自己的特征，但是却都是按照同一个规律运转。究竟看到的实物是否是真实的呢？我很怀疑。如果我们闭上五感，或许就不会被那许多东西迷惑。</div>
<div>往小处，系统中各种信息元素，都会有不同的数据结构。如何使它们正确的运转起来？架构师就像造物主一样，需要设定一套规律。好的架构，总是非常简洁有力，难以了解究竟是为什么。从另外一个角度看，如果能把复杂的事情变的简单，或许这才算是达到一定境界。<br />
<br />
...<br />
<br />
<h4 class="TextColor1" id="subjcns!5B1B17C22A4676AD!832" style="margin-bottom: 0px;">BI</h4>
<div id="msgcns!5B1B17C22A4676AD!832">
<div>(續&lt;死去&gt;)</div>
<div>(NOTE:業務流程不是行政流程^^)</div>
<div>根本的規律我們現在還無法很好的認識以及利用.但是我們可以發現當前的規律,並且有效利用它.</div>
<div>業務實體具有相對的穩定性.但是無論這些業務實體的結構如何,只有在業務流程中運轉才能體現出價值.</div>
<div>現在BI發展的層級為數據報表,數據分析,數據挖掘(Data Mining).</div>
<div>這些都是在現有數據基礎上進行收集整理,如果有在實際業務中起很重要作用,但是現有未被捕獲,這個時候所有這些分析挖掘的操作意義都不會很大.</div>
<div>數據挖掘完成是為了商業決策,但是,如果僅僅使用自己的資料,依然無法起到合理的作用.一般這個時候需要專業的商業諮詢公司的資料進行綜合分析.</div>
<div>決策之後會發成業務方向上的調整,這些調整都會導致業務流程上的變動,或者更精確些是業務邏輯的變動.</div>
<div>這個時候似乎發生了一個問題,  一般信息系統都是依據現有業務邏輯進行設計及實現,其目的是為了數據發掘或者是輔助決策,當決策發生導致業務邏輯變化後,現有系統必須進行適應.如何能夠達到這種時效性??</div>
<div>系統構建中,合理切分組件變的尤為重要.另外,必須清楚的認識到,對於使用者而言,組件化的意義是為了替換.對於組件提供商的意義才是重用.而這些,恰好是和新興古典經濟學在勞動分工上的觀點有一致性. <br />
</div>
</div>
<br />
(2006/01/10)</div>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/56986#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><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><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 02 Mar 2007 13:49:40 +0800</pubDate>
        <link>http://softforce.group.javaeye.com/group/blog/56986</link>
        <guid>http://softforce.group.javaeye.com/group/blog/56986</guid>
      </item>
      <item>
        <title>无Management</title>
        <author>basicbest</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://basicbest.javaeye.com">basicbest</a>&nbsp;
          链接：<a href="http://softforce.group.javaeye.com/group/blog/56984" style="color:red;">http://softforce.group.javaeye.com/group/blog/56984</a>&nbsp;
          发表时间: 2007年03月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <div id="msgcns!5B1B17C22A4676AD!797">
<div>从J2EE的本质： Container-based Compoments  Management上，可以看出，这里把问题归结到了Management上了。而管理是干啥的，就是协调啦。为什么要协调呢？因为资源有限。为什么资源会有限呢？因为人类，能看见的只有一部分，当然，还有非人类那些，可能我就是，活活。从本质上来说，这个世界就是无。好啦，原因找到，现在回到现实世界，现实世界既然是在午这个不是东西的东西上建立起来的，那么，她一定符合无的规则，也就是无规则。这就是说，规则原本是没有的，建了以后，才有规则。人是干啥的呢？既不会创造，来这里干吗呢？反正最后都是无。不好意思，远了......</div>
<div>资源竞争，而产生的协调，这就是管理发生的本质。</div>
<div>所以，似乎问题在于资源调度......</div>
<div>难怪，操作系统那么重要，，，</div>
<div>难怪，偶们就是搞不定，，，，</div>
<div>所以,经济学,,,,,偶未来的重点。</div>
<div>当然，既不是宏观经济，也不是微观经济，而是，，，</div>
<div>偶也不知道，它们应该可以统一起来吧。<br />
<br />
<br />
(2005/12/26)</div>
</div>
          <br/>
          <span style="color:red;">
            <a href="http://softforce.group.javaeye.com/group/blog/56984#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/ad