⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 如何用jdo开发数据库应用.htm

📁 本文将介绍如何使用Sun公司的最新《Java Data Objects 》规范来进行基于数据库的简单应用程序的开发
💻 HTM
📖 第 1 页 / 共 5 页
字号:
    public static class TooMuchOverDraftException extends RuntimeException {}
</PRE>
<P>然后,修改Main.main():</P><PRE>&nbsp;
    public static void main(String[] args) throws Exception {
        System.out.println("开始测试功能……");

        float balance = buySomething("1979371451-1",250.0f,"223003433995431237");
        System.out.println("刷卡成功!余额:"+balance);
    }</PRE>
<P>运行结果:<BR>开始测试功能……<BR>刷卡成功!余额:250.0<BR></P>
<P>嗯,好东西,再买一个:<BR>开始测试功能……<BR>刷卡成功!余额:0.0<BR></P>
<P>啊,卡上没钱了?! 不过这是信用卡嘛,我再买!运行:<BR>开始测试功能……<BR>刷卡成功!余额:-250.0<BR></P>
<P>哈哈,已经透支了,不过透支上限有5000大洋呢!我再买……<BR>算了,还是打住吧,免得银行查下来,说我教唆用户恶意透支,有损我个人声誉。</P>
<H4>4.5.4. 存款</H4>
<P>存款,顾名思义,就是将现金存入信用卡,这样可以刷卡买更多的商品(这也要解释???)。</P>
<P>如果已经透支了,那这个时候进行的存款操作可以称作是“补仓”,哈哈,股票的术语我们借用一下。</P>
<P>方法Main.deposit():</P><PRE>    /**
     * 存款。
     * 对于存款,我们不设最多可存多少钱的限制,因此,这个方法不扔出异常。
     * @param cardId 信用卡标识。这是通过PersistenceManager.getObjectId()得来的。
     * @param amount 存款额
     * @return 存款后的余额
     */
    public static float deposit(String cardId, float amount) {
        //assert amount &gt; 0; //保证存款额是正数。(可以说是废话)
        PersistenceManager pm = getPersistenceManager();
        pm.currentTransaction().begin();
        CreditCard cc = (CreditCard)
            pm.getObjectById(pm.newObjectIdInstance(CreditCard.class,cardId),false);

        cc.setBalance(cc.getBalance()+amount);
        pm.currentTransaction().commit();</PRE><PRE>        float balance = cc.getBalance();
        pm.close();

        return balance;
    }
</PRE>
<P>Main.main()改成:</P><PRE>    public static void main(String[] args) throws Exception {
        System.out.println("开始测试功能……");

        float balance = deposit("1979371451-1",168.0f);
        System.out.println("存款168元后,余额是:"+balance);
    }</PRE>
<P>运行之,结果如下:<BR>开始测试功能……<BR>存款168元后,余额是:-82.0<BR><BR>为什么存168块钱呢?一来这个月迟到太多,工资被狂扣,二来,这个数字比较吉利,还可以剩点钱买碗面吃:(。(有没有这么可怜啊???)</P>
<P>总算又过了一个月,又发工资了,再存:<BR>开始测试功能……<BR>存款168元后,余额是:86.0<BR></P>
<P>嘿,总算摆脱了透支的阴影,咱大老爷们的,总算能挺直腰板儿做人了!</P>
<P>唉,这祖宗传下来的观念就象三座大山,压死人了!瞧别人老美,没有一个不错钱(透支)的,别人活着多精神!咱太老实,借点钱就象是前世欠别人一样,心理负担太沉重,搞不好性格分裂,精神崩溃啊……</P>
<H4>4.5.5. 查询透支报表</H4>
<P>这个功能是查询当前系统中已经处于透支状态的那些信用卡,这里我们将会用到条件过滤,也就是使用JDO的查询语言JDOQL。在Main中加一个方法 
listOverDrafts():</P><PRE>    /**
     * 列出已经透支的信用卡。
     */
    public static void listOverDrafts() {
        PersistenceManager pm = getPersistenceManager();
        Query q = pm.newQuery(CreditCard.class,"balance &lt; 0"); //过滤条件
        Collection col = (Collection)q.execute();
        for(Iterator itr = col.iterator(); itr.hasNext(); ) {
            System.out.println(itr.next());
        }

        pm.close();
    }
</PRE>
<P>我们注意到,经过刚才的一系列操作后,目前还没人透支(张三吓出一身冷汗,幸好刚才补了仓!)。再执行这个方法之前,我们再让张三买点东西,改一下main()方法,还是调用:buySomething("1979371451-1",250.0f,"223003433995431237"); 
结果如下:<BR>开始测试功能……<BR>刷卡成功!余额:-164.0 </P>
<P>可怜的张三又背上了沉重的心理负担。</P>
<P>下面我们改一下Main.main(),调用列出透支信用卡方法:</P><PRE>    public static void main(String[] args) throws Exception {
        System.out.println("开始测试功能……");

        System.out.println("以下是透支的信用卡列表:");
        listOverDrafts();
    }
&nbsp;</PRE>
<P>运行,结果如下:<BR>开始测试功能……<BR>以下是透支的信用卡列表:<BR>信用卡:余额=-164.0,持卡人=张三,身份证号=223003433995431237,电话=020-38864157<BR></P>
<P>我们快马加鞭,继续挺进下一需求功能。</P>
<H4>4.5.6. 查询交易明细</H4>
<P>这个功能相对复杂一点,不过也只是理解上复杂,代码还是很简单的。我们在Main中增加一个方法 listTransactions():</P><PRE>    /**
     * 列出某信用卡的交易明细。
     * @param idcard 身份证号
     */
    public static void listTransactions(String idcard) {
        PersistenceManager pm = getPersistenceManager();
        Query q = pm.newQuery(TransactionRecord.class,
            "card.idcard==_p0"); //过滤条件
        q.declareParameters("String _p0"); //声明查询参数表
        q.setOrdering("createTime ascending"); //按时间顺序列出

        Collection col = (Collection)q.execute(idcard); //按指定身份证号查询
        for(Iterator itr = col.iterator(); itr.hasNext(); ) {
            System.out.println(itr.next());
        }</PRE><PRE>        pm.close();
    }
</PRE>
<P>在这个方法中,我们用到了JDOQL最吸引人的特性之一:对象引用,即“card.idcard==_p0”,这样实际上相当于两个数据表联表查询,显然,这样的语句更易理解,更简洁!此外,我们用到了查询参数“_p0”,最后还用到了排序。实际上,还可以按此类所引用的其它类的属性进行排序,比如按持卡人姓名顺序列出所有交易记录,排序语句将是:q.setOrdering("card.name 
ascending"); 又省下表连接的冗长SQL语句。</P>
<P>最后,我们再修改Main.main()方法:</P><PRE>&nbsp;
    public static void main(String[] args) throws Exception {
        System.out.println("开始测试功能……");

        System.out.println("以下是张三的交易记录:");
        listTransactions("223003433995431237");
    }</PRE>
<P>运行之,结果如下:<BR>开始测试功能……<BR>以下是张三的交易记录:<BR>交易记录:持卡人=张三,身份证号=223003433995431237,交易额=250.0,时间=Mon 
Jun 30 09:24:51 GMT 2003<BR>交易记录:持卡人=张三,身份证号=223003433995431237,交易额=250.0,时间=Mon 
Jun 30 09:25:34 GMT 2003<BR>交易记录:持卡人=张三,身份证号=223003433995431237,交易额=250.0,时间=Mon 
Jun 30 09:27:24 GMT 2003<BR>交易记录:持卡人=张三,身份证号=223003433995431237,交易额=250.0,时间=Mon 
Jun 30 09:29:15 GMT 2003<BR>交易记录:持卡人=张三,身份证号=223003433995431237,交易额=250.0,时间=Mon 
Jun 30 09:29:53 GMT 2003<BR>交易记录:持卡人=张三,身份证号=223003433995431237,交易额=250.0,时间=Mon 
Jun 30 10:35:57 GMT 
2003<BR><BR>这些就是我们前面的几次调用产生的交易记录。实际上,存款记录也应该算是交易记录,只不过本系统中暂时没有这种需求。(注意了,以后提需求的时候要多加考虑才行,否则又会让开发商钻空子了!)</P>
<H3>4.6. 让程序更实用些</H3>
<P>上面我们已经完成了所有的需求功能,大家也看到了基于JDO的应用是如何开发的,需要哪些配置。我再次说明一下,JDOGenie是最方便学习JDO的工具,尽管每隔一个月你得去重新索取一个试用license。</P>
<P>话又说回来,上面这些完成业务逻辑的方法太简单了,不被开发主管打才怪!(参见:<A 
href="http://www.javaresearch.org/members/sun2bin/boss.mpeg">程序写得烂被主管狂扁!</A>)</P>
<P>为了让程序更实用,我们需要将其改造成一个真正的应用,这就涉及到安全性、性能优化与索引创建、容易操作的界面、后台操作日志、备份、图文并茂的报表,等等等等。尽管这些已经超出本文的范围,我们下面还是进行一点简单的讨论。</P>
<P>一般有两种最常见的方式做这样的系统:独立的GUI程序或者基于浏览器的Web应用。下面分别给出两种方式下的建议:</P>
<H4>4.6.1. 图形界面的独立程序</H4>
<P>首先,我们要从java.awt.Frame扩展出一个子类,在其窗口中放入几个Panel,分别对应需求中的几项功能,如果该功能是需要输入参数的,则在相应的Panel中放几个TextField,然后给一个提交按钮;如果该功能不需要输入参数,则直接给一个功能按钮即可。每个按钮的事件响应中,将相关的参数从界面元素中读出,传入到相应的方法中,然后接收方法的返回,将结果打印在界面的输出区(对了,还需要在界面上加一个输出区域,比如TextArea)。</P>
<P>前面我们的Main类的业务逻辑方法中,很多地方都是直接打印了查询取得的数据,在独立GUI程序中不能这样做,只能将查询取得的数据(如Collection)返回到调用的按钮事件中,再由按钮事件处理的代码打印到输出区域。这也算是一种MVC的方式了,呵呵。</P>
<P>还有一点建议,由于pm.close()后,对象的属性不能保证准确读出,所以,在独立的GUI程序中,最好系统一直保留一个打开的pm,各个方法共享。</P>
<H4>4.6.2. 采用JSP的Web应用</H4>
<P>基于JSP的Web应用相对复杂一些,我们需要将jdogenie.jar(合并了jta.jar和其license文件的包)和mysql.jar放到应用的/WEB-INF/lib中,然后将自己的enhance过的类代码按目录结构放到/WEB-INF/classes/中,同时配置文件creditSys.jdogenie和system.jdo一并放到/WEB-INF/classes/目录中。</P>
<P>这些只是目录的配置,我们还需要对前面的代码进行改造。</P>
<P>首先,与独立的GUI程序一样,需要将直接通过System.out.println()输出的业务逻辑方法改为将查询所得的Collection或具体对象返回到调用者。这里的调用者就是JSP。我们可以对每个功能写一到两个jsp,这些JSP只完成数据输入和显示的作用,这一点与独立的程序差不多。</P>
<P>不过,由于Web应用是多线程的,就需要考虑到并发连接的问题,因此系统中不能只设置一个始终打开的PM,而是每个页面请求需要使用一个PM。为了能在一个页面请求的处理过程中在不同的代码片断里共享一个PM,你可以参考<A 
href="http://www.jdocentral.com/forums/index.php?act=ST&amp;f=11&amp;t=625&amp;s=dba82950d9e12ad45210429166dcf4fa">我在JDOCentral的论坛上发表的这篇贴子</A>。</P>
<P>关于Web应用中PM连接池和资源释放的细节已经超出本文的范围,请参考我在CSDN上发表的其它关于JDO的文章(见本文尾部的“参考文章”)。</P>
<H2>5. 总结</H2>
<P>下面我们对以上的基于JDO的开发作一点总结。</P>
<H3>5.1. 开发流程的变化</H3>
<P>基于JDO开发的流程在本文开始处通过一幅图进行了介绍,主要增加了两个步骤:编写metadata,和根据metadata对类代码进行增强。而这两步通过JDOGenie的工作台很容易搞定,都是自动化的。</P>
<P>剩下的开发过程就比原始的JDBC包装简单多了,我们不再有SQL代码,不再有复杂的“增、删、改、查”通用接口,不再有不支持事务的担心,不再有……我们只需要在一个完全面向对象的数据对象模型上通过JDO的API进行操作即可。</P>
<P>另外一点,我们可以看到,基于JDO的开发中,各种开发角色(JavbaBean编写、JSP编写、数据库维护、配置)都是基于数据对象模型进行开发,比如说,用JDOGenie就可以生成数据模型的UML类图后,打印下来,交给各个开发参与人员,无论是写控制类JavaBean,还是JSP,还是数据库结构维护,都可以以这个图作基准,大家统一进行开发,而不是象基于JDBC的应用,大家都基于数据库结构进行开发。</P>
<P>JDO给我们带来的太多了,需要在开发过程中慢慢体会。</P>
<H3>5.2. 速度会不会慢?--性能测试数据参考</H3>
<P>我使用过一个有一定规模的应用来测试过JDO的性能,这个应用具有十多个类,每个类有5~20个属性,类之间有错综复杂的关系,功能很多,是一个完整的基于浏览器的Web应用。使用原始的自己的JDBC包装时,数据库相关的处理代码非常多,有10多K,而改造JDO后,这些代码都没了,实际上,相当于这些代码变成了JDO厂商的支持包。</P>
<P>接着是性能测试,原来的基于JDBC的应用每秒可处理8个请求,而采用JDOGenie作底层的JDO应用每秒可处理35个请求,采用KodoJDO作底层的JDO应用(手写的Java代码与JDOGenie一样)时,每秒可处理25个请求。这一切都归功于JDO规范所规定的延迟读取机制(Lazy 
Loading Mechanism)。</P>
<P>可能有眼尖的读者会问:为什么文章开头说Kodo是性能王者,而这里却不如JDOGenie呢?不错,眼睛实在是雪亮!这样的材质,怎么不去做私家侦探啊!搞个什么X美凤的片子,肯定一炮走红!<BR>哦,对了,我还没给出解释。我前面说Kodo性能最好,是包括对稳定性的评价在内的。我这里对两者的测试,都是采用了JDO规范定义的乐观事务方式(javax.jdo.option.OptimisticTransaction),这种方式将事务的锁定限制在应用端,不对数据库造成压力,只是在对同一对象的并发改动很多的时候会导致很多冲突。一般来说,你的Web应用不会一天访问量上百万吧?如果不到,就完全可以采用这种事务处理方式。Kodo的事务处理在测试中成功机会比JDOGenie大很多,同样的测试时间,Kodo的类似访问数的统计数据比JDOGenie要多,也就是说Kodo的成功事务比JDOGenie多,尽管总访问数少于JDOGenie。综上所述,Kodo的性能还是要比JDOGenie好。不过JDOGenie也在奋起直追,我对它比较看好!</P>
<H3>5.3. 还有些不爽--JDO1.0的局限性</H3>
<P>好了,兴奋过后,应该是冷静的反思。</P>
<P>有一句话说得好,最值得相信的人,只有你自己!</P>
<P>我是一名JDO的狂热追随者,为推广JDO做着不懈的努力,当然免不了某些时候言语过激或片面化,所谓“一叶障目,不见泰山”。就象Java追随者认为.NET一无是处一样,实际上.NET有很多优点是Java无

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -