`
yuxingfirst
  • 浏览: 50555 次
  • 性别: Icon_minigender_1
  • 来自: 湘潭
社区版块
存档分类
最新评论

高级DAO编程

    博客分类:
  • J2EE
阅读更多
在整个应用程序中使用数据访问对象(DAO)使我们可以将底层数据访问逻辑与业务逻辑分离开来。我们构建了为每一个数据源提供 GRUD (创建、读取、更新、删除)操作的 DAO 类。

在本文中,我将为您介绍构建更好的 DAO 类的 DAO 实现策略和技术。更确切地说,我将讨论日志、异常处理和事务界定。您将学到如何将这三者结合到自己的 DAO 类中。本文假定您熟悉 JDBC API、SQL 和关系数据库编程。

我们将以对 DAO 设计模式和数据访问对象的概述开始。

DAO基础

DAO 模式是标准 J2EE 设计模式之一。开发人员用这种模式将底层数据访问操作与高层业务逻辑分离开。一个典型的 DAO 实现有以下组件:

    * 一个 DAO 工厂类
    * 一个 DAO 接口
    * 一个实现了 DAO 接口的具体类
    * 数据传输对象(有时称为值对象)

具体的 DAO 类包含访问特定数据源的数据的逻辑。在下面一节中您将学习设计和实现数据访问对象的技术。有关 DAO 设计模式的更多内容请参阅 参考资料。

事务界定

关于 DAO 要记住的重要一点是它们是事务性对象。由 DAO 所执行的每一个操作 -- 如创建、更新或者删除数据 -- 都与一个事务相关联。因此, 事务界定的概念就变得特别重要了。

事务界定是定义事务边界的方式。J2EE 规范描述了两种事务界定的模型:编程式(programmatic)和声明式(declarative)。表 1 分析了这两种模型:


声明式事务界定 编程式事务界定
程序员用 EJB 部署描述符声明事务属性。 程序员负责编写事务逻辑。
运行时环境(EJB 容器)用这些属性自动管理事务。 应用程序通过一个 API 控制事务。

我们将侧重于编程式事务界定。

设计考虑

如前所述,DAO 是事务性对象。一个典型的 DAO 执行像创建、更新和删除这样的事务性操作。在设计 DAO 时,首先要问自己以下问题:

    * 事务要如何开始?
    * 事务应如何结束?
    * 哪一个对象将负责开始一个事务?
    * 哪一个对象将负责结束一个事务?
    * DAO 是否要负责事务的开始和结束?
    * 应用程序是否需要通过多个 DAO 访问数据?
    * 事务涉及到一个 DAO 还是多个 DAO?
    * 一个 DAO 是否调用另一个 DAO 的方法?

了解上述问题的答案将有助于您选择最适合的 DAO 的事务界定策略。在 DAO 中有两种主要的界定事务的策略。一种方式是让 DAO 负责界定事务,另一种将事务界定交给调用这个 DAO 方法的对象处理。如果选择了前一种方式,那么就将事务代码嵌入到 DAO 中。如果选择后一种方式,那么事务界定代码就是在 DAO 类外面。我们将使用简单的代码示例帮助您更好理解每一种方式是如何工作的。

清单 1 显示了一个有两种数据操作的 DAO:创建和更新:

清单 1. DAO 方法

       public void createWarehouseProfile(WHProfile profile);
       public void updateWarehouseStatus(WHIdentifier id, StatusInfo status);


清单 2 显示了一个简单的事务。事务界定在 DAO 类外面。注意在这个例子中调用者是如何在一个事务中结合多个 DAO 操作的。

清单 2. 调用者管理的事务

      tx.begin();    // start the transaction
      dao.createWarehouseProfile(profile);
      dao.updateWarehouseStatus(id1, status1);
      dao.updateWarehouseStatus(id2, status2);
      tx.commit();   // end the transaction


这种事务界定策略对于需要在一个事务中访问多个 DAO 的应用程序特别有用。

可以用 JDBC API 或者 Java 事务 API(Java Transaction API JTA)实现事务界定。 JDBC 事务界定比 JTA 事务界定要简单,但是 JTA 提供了更多的灵活性。在下面一节中我将更深入地分析事务界定的机制。




回页首


用 JDBC 进行事务界定

JDBC 事务是用 Connection 对象控制的。JDBC Connection 接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。 java.sql.Connection 提供了以下控制事务的方法:

    * public void setAutoCommit(boolean)
    * public boolean getAutoCommit()
    * public void commit()
    * public void rollback()

清单 3 显示了如何用 JDBC API 界定一个事务:

清单 3. 用 JDBC API 进行事务界定

      import java.sql.*;
      import javax.sql.*;
      // ...
      DataSource ds = obtainDataSource();
      Connection conn = ds.getConnection();
      conn.setAutoCommit(false);
      // ...
      pstmt = conn.prepareStatement("UPDATE MOVIES ...");
      pstmt.setString(1, "The Great Escape");
      pstmt.executeUpdate();
      // ...
      conn.commit();
      // ...


使用 JDBC 事务界定时,您可以将多个 SQL 语句结合到一个事务中。JDBC 事务的一个缺点是事务的范围局限于一个数据库连接。一个 JDBC 事务不能跨越多个数据库。在下面,我们将看一下如何用 JTA 进行事务界定。因为 JTA 不像 JDBC 那样有名,所以我们首先做一个简介。




回页首


JTA简介

Java 事务 API(JTA) 及其同门兄弟 Java 事务服务(Java Transaction Service JTS)为 J2EE 平台提供了分布式事务服务。一个 分布式的事务涉及一个事务管理器和一个或者多个资源管理器。一个 资源管理器是任何类型的持久性的数据存储。事务管理器负责协调所有事务参与者之间的通信。事务管理器与资源管理器之间的关系如图 2 所示:

图 2. 一个事务管理器和资源管理器
一个事务管理器和资源管理器

JTA 事务比 JDBC 事务功能更强。JDBC 事务局限为一个数据库连接,而 JTA 事务可以有多个参与者。所有下列 Java 平台组件都可以参与 JTA 事务:

    * JDBC 连接
    * JDO PersistenceManager 对象
    * JMS 队列
    * JMS 主题
    * 企业 JavaBeans
    * 符合 J2EE 连接体系结构(J2EE Connector Architecture)规范的资源适配器





回页首


使用 JTA 的事务界定

要用 JTA 进行事务界定,应用程序要调用 javax.transaction.UserTransaction 接口中的方法。清单 4 显示了对 UserTransaction 对象的典型 JNDI 查询:

清单 4. 一个对 UserTransaction 对象的 JDNI 查询

      import javax.transaction.*;
      import javax.naming.*;
      // ...
      InitialContext ctx = new InitialContext();
      Object txObj = ctx.lookup("java:comp/UserTransaction");
      UserTransaction utx = (UserTransaction) txObj;


当应用程序找到了 UserTransaction 对象后,就可以开始事务了,如清单 5 所示:

清单 5. 用 JTA 开始一个事务

      utx.begin();
      // ...
      DataSource ds = obtainXADataSource();
      Connection conn = ds.getConnection();
      pstmt = conn.prepareStatement("UPDATE MOVIES ...");
      pstmt.setString(1, "Spinal Tap");
      pstmt.executeUpdate();
      // ...
      utx.commit();
      // ...


当应用程序调用 commit() 时,事务管理器用一个两阶段的提交协议结束事务。




回页首


控制事务的 JTA 方法

javax.transaction.UserTransaction 接口提供了以下事务控制方法:

    * public void begin()
    * public void commit()
    * public void rollback()
    * public int getStatus()
    * public void setRollbackOnly()
    * public void setTransactionTimeout(int)

应用程序调用 begin() 开始事务。应用程序调用 commit() 或者 rollback() 结束事务。参阅 参考资料以了解更多关于用 JTA 进行事务管理的内容。




回页首


使用 JTA 和 JDBC

开发人员通常在 DAO 类中用 JDBC 进行底层数据操作。如果计划用 JTA 界定事务,那么就需要有一个实现 javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驱动程序。一个实现了这些接口的驱动程序将可以参与 JTA 事务。一个 XADataSource 对象就是一个 XAConnection 对象的工厂。 XAConnection s 是参与 JTA 事务的 JDBC 连接。

您将需要用应用服务器的管理工具设置 XADataSource 。从应用服务器和 JDBC 驱动程序的文档中可以了解到相关的指导。

J2EE 应用程序用 JNDI 查询数据源。一旦应用程序找到了数据源对象,它就调用 javax.sql.DataSource.getConnection() 以获得到数据库的连接。

XA 连接与非 XA 连接不同。一定要记住 XA 连接参与了 JTA 事务。这意味着 XA 连接不支持 JDBC 的自动提交功能。同时,应用程序一定不要对 XA 连接调用 java.sql.Connection.commit() 或者 java.sql.Connection.rollback() 。相反,应用程序应该使用 UserTransaction.begin()、 UserTransaction.commit() 和 serTransaction.rollback() 。




回页首


选择最好的方式

我们讨论了如何用 JDBC 和 JTA 界定事务。每一种方式都有其优点,您需要决定哪一种最适合于您的应用程序。

在最近的许多项目中,我们小组是用 JDBC API 进事务界定来构建 DAO 类的。这些 DAO 类可以总结如下:

    * 事务界定代码嵌入在 DAO 类中。
    * DAO 类使用 JDBC API 进行事务界定。
    * 调用者不能界定事务。
    * 事务范围局限于单个 JDBC 连接。

JDBC 事务并不总是适合复杂的企业应用程序。如果您的事务要跨越多个 DAO 或者多个数据库,那么下列实现策略也许更合适:

    * 事务用 JTA 界定。
    * 事务界定代码从 DAO 中分离出来。
    * 调用者负责界定事务。
    * DAO 加入一个全局事务。

JDBC 方式由于其简单性而具有吸引力,JTA 方式提供了更大的灵活性。您所选择的实现将取决于应用程序的特定需求。




回页首


日志记录和 DAO

一个良好实现的 DAO 类将使用日志记录来捕捉有关其运行时行为的细节。您可以选择记录异常、配置信息、连接状态、JDBC 驱动程序元数据、或者查询参数。日志对于开发的所有阶段都很有用。我经常在开发时、测试时和生产中分析应用程序日志。

在本节,我将展示一个显示如何将 Jakarta Commons Logging 加入到 DAO 中的代码示例。在这之前,让我们回顾一下一些基本知识。

选择日志库

许多开发人员使用一种原始格式进行日志记录: System.out.println 和 System.err.println 。 Println 语句速度快且使用方便,但是它们没有提供全功能的日志记录系统所具有的功能。表 2 列出了 Java 平台的日志库:

表 2. Java 平台的日志库

日志库 开放源代码? URL
java.util.logging 不是 http://java.sun.com/j2se/
Jakarta Log4j 是 http://jakarta.apache.org/log4j/
Jakarta Commons Logging 是 http://jakarta.apache.org/commons/logging.html

Jakarta Commons Logging 可以与 java.util.logging 或者 Jakarta Log4j 一同使用。Commons Logging 是一个日志抽象层,它隔离了应用程序与底层日志实现。使用 Commons Logging,您可以通过改变配置文件更换底层日志实现。Commons Logging 在 Jakarta Struts 1.1 和 Jakarta HttpClient 2.0 中使用。

一个日志记录示例

清单 7 显示了如何在 DAO 类中使用 Jakarta Commons Logging:

清单 7. DAO 类中的 Jakarta Commons Logging

import org.apache.commons.logging.*;
class DocumentDAOImpl implements DocumentDAO
{
      static private final Log log = LogFactory.getLog(DocumentDAOImpl.class);
      public void deleteDocument(String id)
      {
          // ...
          log.debug("deleting document: " + id);
          // ...
          try
          {
              // ... data operations ...
          }
          catch (SomeException ex)
          {
              log.error("Unable to delete document", ex);
              // ... handle the exception ...
}
      }
}


日志记录是所有任务关键型应用程序的重要部分。如果在 DAO 中遇到故障,那么日志通常可以提供判断出错位置的最好信息。将日志加入到 DAO 可以保证您有机会进行调试和故障排除。




回页首


DAO 中的异常处理

我们讨论过了事务界定和日志,现在对于如何在数据访问对象上应用它们有了更深入的理解。我们的第三个和最后一个讨论议题是异常处理。遵从几个简单的异常处理指导可以使您的 DAO 更容易使用、更健壮及更易于维护。

在实现 DAO 模式时,考虑以下问题:

    * DAO 的公共接口中的方法是否抛出检查过的异常?
    * 如果是的话,抛出何种检查过的异常?
    * 在 DAO 实现类中如何处理异常?

在使用 DAO 模式的过程中,我们的小组开发了一些处理异常的原则。遵从这些原则可以极大地改进您的 DAO:

    * DAO 方法应该抛出有意义的异常。
    * DAO 方法不应该抛出 java.lang.Exception 。 java.lang.Exception 太一般化了。它不传递关于底层问题的任何信息。
    * DAO 方法不应该抛出 java.sql.SQLException 。SQLException 是一个低级别的 JDBC 异常。一个 DAO 应该力争封装 JDBC 而不是将 JDBC 公开给应用程序的其余部分。
    * 只有在可以合理地预期调用者可以处理异常时,DAO 接口中的方法才应该抛出检查过的异常。如果调用者不能以有意义的方式处理这个异常,那么考虑抛出一个未检查的(运行时)异常。
    * 如果数据访问代码捕获了一个异常,不要忽略它。忽略捕获的异常的 DAO 是很难进行故障诊断的。
    * 使用链接的异常将低级别的异常转化为高级别的异常。
    * 考虑定义标准 DAO 异常类。Spring Framework (参阅 参考资料)提供了很好的一套预定义的 DAO 异常类。

有关异常和异常处理技术的更多信息参阅 参考资料。

原文参考:http://www.ibm.com/developerworks/cn/java/j-dao
分享到:
评论

相关推荐

    高级DAO编程技巧--软件工程师

    ### 高级DAO编程技巧详解 #### 一、引言 在现代软件开发中,特别是J2EE领域,数据访问对象(Data Access Object, DAO)的设计模式被广泛应用于分离低级别的数据访问逻辑与高级别的业务逻辑。通过这种方式,开发者...

    VC++6.0高级MFC编程

    数据库编程也是MFC的一大特色,可能会讲解ODBC(Open Database Connectivity)和DAO(Data Access Objects)接口,以及如何使用MFC的CDatabase、CRecordset等类进行数据库操作。网络编程方面,MFC提供了CSocket类来...

    vc++高级编程;vc++高级编程

    vc++高级编程: 一 走进Visual C++ * 1 理解VC工程 * 2 MFC编程特点 * 3使用Wizard * 二 MFC程序结构分析 * 1 WINDOWS程序工作原理 * 2 建立应用程序 * 3 程序结构剖析 * 3.1 类CMYAPP * 3.2 类CMAINFRAME...

    VC++高级编程.chm

    chm格式的 VC++高级编程。一本很好的学习教程。本书目录: 目录 一 走进Visual C++ 1 理解VC工程 2 MFC编程特点 3使用Wizard 二 MFC程序结构分析 1 WINDOWS程序工作原理 2 建立应用程序 3 程序结构...

    Java服务器高级编程

    在Java服务器高级编程领域,开发者通常需要掌握一系列深入的技术和概念,以构建高效、可扩展且可靠的网络应用程序。本文将围绕Java服务器编程的关键知识点展开,包括但不限于Servlet、JSP、EJB、Spring框架、微服务...

    Visual C++6_0数据库高级编程(完整版).part2.rar

    第2篇(实例篇)通过6个编程实例详细介绍了ODBC,DAO,OLEDB以及ADO的客户端数据库的访问技术;第3篇(高级篇)通过2个实例介绍了OLEDB和ADO的高级编程技术。附录A是数据库访问的错误代码;附录B介绍了数据库编程资源...

    Visual C++6_0数据库高级编程(完整版).part1.rar

    第2篇(实例篇)通过6个编程实例详细介绍了ODBC,DAO,OLEDB以及ADO的客户端数据库的访问技术;第3篇(高级篇)通过2个实例介绍了OLEDB和ADO的高级编程技术。附录A是数据库访问的错误代码;附录B介绍了数据库编程资源...

    (书+++源代码)

    ++++++很经典的一本学习vc++数据库编程的书+++++++ +++++++内附有pdf与word两种版本+++++++++++++++ ++++++++以及原书附带的源代码++++++++++++++++++ ...第3篇(高级篇)通过2个实例介绍了OLE DB和ADO的高级编程技术!

    MFC Access 数据库编程 第 3 篇 高级话题

    在深入探讨MFC Access数据库编程的高级话题之前,先来理解一下MFC(Microsoft Foundation Classes)框架是如何与Access数据库交互的。MFC是Microsoft提供的一种C++类库,用于简化Windows应用程序开发,其中包括对...

    java高级编程项目实践

    Java高级编程项目实践是针对已经掌握了基础Java编程的开发者,旨在提升其在实际开发中的技能和经验。这个项目教程涵盖了从需求定义、用户界面设计、数据库设计到类和接口的实现等多个关键步骤,全面展示了如何构建一...

    Access 2000中文版高级编程(part1)

    Access2000中文版高级编程 目录 第一部分 编程基础 1 第1章 宏与代码 3 1.1 何时使用代码代替宏 4 1.1.1 何时用宏 4 1.1.2 何时用代码 4 1.2 宏到代码的转换 5 1.2.1 使用DoCmd对象 5 1.2.2 与宏命令等价...

    Access+2000中文版高级编程

    Access2000中文版高级编程 目录 第一部分 编程基础 1 第1章 宏与代码 3 1.1 何时使用代码代替宏 4 1.1.1 何时用宏 4 1.1.2 何时用代码 4 1.2 宏到代码的转换 5 1.2.1 使用DoCmd对象 5 1.2.2 与宏...

    VC++数据库编程(doc格式,强烈推荐)

    DAO数据库编程章节则讲述了DAO数据访问的原理,包括DAO对象和MFC对DAO的支持,以及与ODBC的比较。最后,OLE DB客户数据库编程和ADO客户数据库编程章节分别介绍了OLE DB的结构、优越性和客户模板,以及ADO的原理、...

    东北大学面向对象编程高级编程实验教程

    东北大学面向对象编程高级编程实验教程 本课程实验报告主要介绍了使用 JSP 和 Servlet 技术开发图书馆管理系统的设计和实现。该系统具有登录、注册、图书的添加、修改、删除、个人信息查询、修改、退出等功能。 ...

    java dao模式搭建教程

    Java DAO(Data Access Object)模式是一种常见的软件设计模式,它在Java应用中被广泛用于分离业务...继续深入学习,你可以研究更多高级特性,如AOP(面向切面编程)、Caching(缓存)等,进一步优化你的数据访问层。

    ADO.NET高级编程.pdf

    ### ADO.NET高级编程知识点概览 #### 一、引言 - **ADO.NET简介**:ADO.NET(ActiveX Data Objects .NET)是Microsoft推出的一种数据访问技术,它基于.NET框架,提供了一种用于访问数据库和其他数据源的高效且灵活...

    vb 高级编程 pdg版

    "vb 高级编程 pdg版"这本书显然专注于提升VB程序员的技能,讲解了如何利用Windows API以及数据库连接技术来扩展VB应用程序的功能。 **Windows API** 是一组预定义的函数,提供了对操作系统底层功能的直接访问。在VB...

    泛型通用DAO,可以很简化DAO层的代码

    在Java编程领域,DAO(Data Access Object)模式是一种常见的设计模式,用于封装对数据库的操作,以解耦业务逻辑层和数据存储层。泛型通用DAO是这种模式的一种优化,它利用了Java 5.0引入的泛型和反射机制,大大简化...

    VB_NET和SOL Server2000高级编程——创建高效数据层

    在VB.NET和SQL Server 2000的高级编程中,构建高效的数据层是至关重要的。数据层作为应用程序的核心部分,负责与数据库进行交互,处理数据的读取、写入和更新操作。以下将详细探讨如何利用VB.NET的ADO.NET框架和SQL ...

Global site tag (gtag.js) - Google Analytics