DAO小摘

来源:互联网 发布:mac os 编辑:程序博客网 时间:2024/05/16 16:13

数据访问对象(DAO)设计模式把底层的数据访问逻辑和高层的商务逻辑分开。实现DAO模式能够更加专注于编写数据访问代码。 为每个数据源创建了提供CRUD(创建,读取,更新,删除)操作的DAO类.

  通常来说,一个典型的DAO模式会有以下几个组件:

  1. 一个DAO工厂类;

  2. 一个DAO接口;

  3. 一个实现DAO接口的具体类,具体的DAO类包含了从特定的数据源访问数据的逻辑

  4. 数据传递对象(有些时候叫做值对象).

关于DAO要记住的一件重要事情是它们是事务性对象。每个被DAO执行的操作(象创建,更新、或删除数据)都是和事务相关联的。

这就涉及到一个事务划分的问题,也就是在事务界定定义中的方式。

通常会分为:编程性事务(programmatic)和声明性事务(declarative)

声明性事务划分 编程性事务划分 程序员使用EJB的布署描述符声明事务属性 程序员担负编写事务逻辑代码的责任。 运行时环境(EJB容器)使用这些属性来自动的管理事务。 应用程序通过一个API接口来控制事务。

DAOS其实就是事务,为了编写DAO,我们应该了解的是:

  1、 事务将怎样开始?

  2、 事务将怎样结束?

  3、 那个对象将承担起动一个事务的责任?

  4、 那个对象将承担结束一个事务的责任?

  5、 DAO应该承担起动和结束事务的责任?

  6、 应用程序需要交叉访问多个DAO吗?

  7、 一个事务包含一个DAO还是多个DAO?

  8、 一个DAO包含其它的DAO中的方法吗?

一种方法是使用DAO承担事务划分的责任;

另一种是延期性事务,它把事务划分到调用DAO对象的方法中。

如果你选择前者,你将要在DAO类中嵌入事务代码。如果你选择后者,事务代码将被写在DAO类的外部。我们将使用简单的代码实例来更好的理解这两种方法是怎样工作的。

来个例子: 

DAO:

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

DAO外部,调用DAO对象:

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(JTA)。

使用JDBC事务划分,你能够把多个SQL语句组合到一个单一事务中。JDBC事务的缺点之一就是事务范围被限定在一个单一的数据库连接中。

Java事务API(JTA;Java Transaction API)和它的同胞Java事务服务(JTS;Java Transaction Service),为J2EE平台提供了分布式事务服务。一个分布式事务(distributed transaction)包括一个事务管理器(transaction manager)和一个或多个资源管理器(resource manager)。一个资源管理器(resource manager)是任意类型的持久化数据存储。事务管理器(transaction manager)承担着所有事务参与单元者的相互通讯的责任。

  一个JTA事务可以有多个参与者,而一个JDBC事务则被限定在一个单一的数据库连接。下列任一个Java平台的组件都可以参与到一个JTA事务中:

  .JDBC连接

  .JDO PersistenceManager 对象

  .JMS 队列

  .JMS 主题

  .企业JavaBeans(EJB)

  .一个用J2EE Connector Architecture 规范编译的资源分配器。

使用JTA和JDBC

  开发人员经常使用JDBC来作为DAO类中的底层数据操作。如果计划使用JTA来划分事务,你将需要一个实现了javax.sql.XADataSource,javax.sql.XAConnection和javax.sql.XAResource接口JDBC的驱动。实现了这些接口的驱动将有能力参与到JTA事务中。一个XADataSource对象是一个XAConnection对象的工厂。XAConnections是参与到JTA事务中的连接。

  你需要使用应用程序服务器管理工具来建立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()和UserTransaction.rollback().

选择最适合的:

如果只需要一个数据库连接:

        .事务划分代码被嵌入到DAO类内部

  .DAO类使用JDBC API来进行事务划分

  .调用者没有划分事务的方法

  .事务范围被限定在一个单一的JDBC连接
如果是在多个连接中进行的话,就应该这样:

.用JTA对事务进行划分

  .事务划分代码被DAO分开

  .调用者承担划分事务的责任

  .DAO参与一个全局的事务中

 

 JDBC方法由于它的简易性而具有吸引力,JTA方法提供了更多灵活性。你选择什么样的实现将依赖于你的应用程序的特定需求。

 日志是评估应用程序的基本部分。如果你在一个DAO中遇到了失败,日志经常会为理解发生的什么错误提供最好的信息。把日志结合到你的DAO中,确保得到调试和解决问题的有效手段。

异常问题:

 .DAO方法应该抛出有意义的异常。

  .DAO方法不应该抛出java.lang.Exception异常。因为java.lang.Exception太一般化,它不能包含有关潜在问题的所有信息。

  .DAO方法不应该抛出java.sql.SQLException异常。SQLException是一个底层的JDBC异常,DAO应用努力封装JDBC异常而不应该把JDBC异常留给应用程序的其它部分。

  .在DAO接口中的方法应该只抛出调用者期望处理的检查性异常。如果调用者不能用适当的方法来处理异常,考滤抛出不检查性(运行时run-time)异常。

.使用异常链把底层的异常传递给高层的某个处理器。

.考滤定义一个标准的DAO异常类。Spring框架提供了一个优秀的预定义的DAO异常类的集合。

 

 实现示例:MovieDAO

  MoveDAO包括事务划分、日志记录和异常处理。你会在Resources段找到MovieDAO的源代码。它被分下面的三个包:

.daoexamples.exception
.daoexamples.move
.daoexamples.moviedemo

  这个DAO模式的实现由下面的类和接口组成:

.daoexamples.movie.MovieDAOFactory
.daoexamples.movie.MovieDAO
.daoexamples.movie.MovieDAOImpl
.daoexamples.movie.MovieDAOImplJTA
.daoexamples.movie.Movie
.daoexamples.movie.MovieImple
.daoexamples.movie.MovieNotFoundException
.daoexamples.movie.MovieUtil

  MovieDAO接口定义了DAO的数据操作。这个接口有如下五个方法:

.public Movie findMovieById(String id)
.public java.util.Collection findMoviesByYear(String year)
.public void deleteMovie(String id)
.public Movie createMovie(String rating,String year,String title)
.public void updateMovie(String id,String rating,String year,String title)

  daoexamples.movie包包含了两个MovieDAO接口的实现。每个实现使用了一个同的事务划分方法,如下表所示:

  MovieDAOImpl MovieDAOImplJTA
实现了MovieDAO接口吗? Yes Yes
通过JNDI获得DataSource吗? Yes  Yes
从一个DataSource获得java.sql.Connection对象吗? Yes  Yes
DAO界定内部的事务吗? Yes  No
使用JDBC事务吗? Yes No
使用一个XA DataSource吗? No  Yes
分担JTA事务吗? No  Yes

  MovieDAO 示范应用程序

  这个示范应用程序是一个叫做daoexamples.moviedemo.DemoServlet.DemoServlet的servlet类,它使用Movie DAO来查询和更新一个表中的movie数据。

  这个servlet示范了把JTA感知的MovieDAO和Java消息服务组合到一个单一的事务中,如示例8所示:

UserTransaction utx = MovieUtil.getUserTransaction();
utx.begin();
batman = dao.createMovie(";R";
";2008";
";Batman Reloaded";);
publisher = new MessagePublisher();
publisher.publishTextMessage(";I’ll be back";);
dao.updateMovie(topgun.getId(),
";PG-13";
topgun.getReleaseYear(),
topgun.getTitle());
dao.deleteMovie(legallyblonde.getId());
utx.commit();

  要运行这个范例应用程序,在你的应用程序服务器中配置一个XA 数据源和一个非XA数据源。然后布署daoexamples.ear文件。这个应用程序将运行在任何与J2EE兼容的应用程序服务器。
      

 

 

 

 

原创粉丝点击