javadao.docx
- 文档编号:29172430
- 上传时间:2023-07-21
- 格式:DOCX
- 页数:22
- 大小:22.75KB
javadao.docx
《javadao.docx》由会员分享,可在线阅读,更多相关《javadao.docx(22页珍藏版)》请在冰豆网上搜索。
javadao
J2EE开发人员使用数据访问对象(DAO)设计模式把底层的数据访问逻辑和高层的商务逻辑分开.实现DAO模式能够更加专注于编写数据访问代码.
我们先来回顾一下DAO设计模式和数据访问对象.
DAO基础
DAO模式是标准的J2EE设计模式之一.开发人员使用这个模式把底层的数据访问操作和上层的商务逻辑分开.一个典型的DAO实现有下列几个组件:
1.一个DAO工厂类;
2.一个DAO接口;
3.一个实现DAO接口的具体类;
4.数据传递对象(有些时候叫做值对象).
具体的DAO类包含了从特定的数据源访问数据的逻辑。
在下面的这段中你将学到设计和实现数据访问对象的技术。
事务划分:
关于DAO要记住的一件重要事情是它们是事务性对象。
每个被DAO执行的操作(象创建,更新、或删除数据)都是和事务相关联的。
同样的,事务划分(transactiondemarcation)的概念是特别重要的。
事务划分是在事务界定定义中的方式。
J2EE规范为事务划分描述了两种模式:
编程性事务(programmatic)和声明性事务(declarative).下表是对这两种模式的拆分:
声明性事务划分编程性事务划分
程序员使用EJB的布署描述符声明事务属性程序员担负编写事务逻辑代码的责任。
运行时环境(EJB容器)使用这些属性来自动的管理事务。
应用程序通过一个API接口来控制事务。
我将把注意力集中的编程性事务划分上。
象前面的介绍一样,DAOs是一些事务对象。
一个典型的DAO要执行象创建、更新、和删除这的事务性操作。
在设计一个DAO时,首先要问自己如下问题:
1、事务将怎样开始?
2、事务将怎样结束?
3、那个对象将承担起动一个事务的责任?
4、那个对象将承担结束一个事务的责任?
5、DAO应该承担起动和结束事务的责任?
6、应用程序需要交叉访问多个DAO吗?
7、一个事务包含一个DAO还是多个DAO?
8、一个DAO包含其它的DAO中的方法吗?
回答这些问题将有助于你为DAO对象选择最好的事务划分策略。
对ADO中的事务划分有两个主要的策略。
一种方法是使用DAO承担事务划分的责任;另一种是延期性事务,它把事务划分到调用DAO对象的方法中。
如果你选择前者,你将要在DAO类中嵌入事务代码。
如果你选择后者,事务代码将被写在DAO类的外部。
我们将使用简单的代码实例来更好的理解这两种方法是怎样工作的。
实例1展示了一个带有两种数据操作的DAO:
创建(create)和更新(update):
publicvoidcreateWarehouseProfile(WHProfileprofile);
publicvoidupdateWarehouseStatus(WHIdentifierid,StatusInfostatus);
实例2展示了一个简单的事务,事务划分代码是在DAO类的外部。
注意:
在这个例子中的调用者把多个DOA操作组合到这个事务中。
tx.begin();//startthetransaction
dao.createWarehouseProfile(profile);
dao.updateWarehouseStatus(id1,status1);
dao.updateWarehouseStatus(id2,status2);
mit();//endthetransaction
这种事务事务划分策略对在一个单一事务中访问多个DAO的应用程序来说尤为重要。
你即可使用JDBCAPI也可以使用Java事务API(JTA)来实现事务的划分。
JDBC事务划分比JTA事务划分简单,但是JTA提供了更好的灵活性。
在下面的这段中,我们会进一步的看事务划分机制。
使用JDBC的事务划分
JDBC事务是使用Connection对象来控制的。
JDBC的连接接口(java.sql.Connection)提供了两种事务模式:
自动提交和手动提交。
Java.sql.Connection为控制事务提供了下列方法:
.publicvoidsetAutoCommit(Boolean)
.publicBooleangetAutoCommit()
.publicvoidcommit()
.publicvoidrollback()
实例3展示怎样使用JDBCAPI来划分事务:
importjava.sql.*;
importjavax.sql.*;
//...
DataSourceds=obtainDataSource();
Connectionconn=ds.getConnection();
conn.setAutoCommit(false);
//...
pstmt=conn.prepareStatement("UPDATEMOVIES...");
pstmt.setString(1,"TheGreatEscape");
pstmt.executeUpdate();
//...
mit();
//...
使用JDBC事务划分,你能够把多个SQL语句组合到一个单一事务中。
JDBC事务的缺点之一就是事务范围被限定在一个单一的数据库连接中。
一个JDBC事务不能够跨越多个数据库。
接下来,我们会看到怎样使用JTA来做事务划分的。
因为JTA不象JDBC那样被广泛的了解,所以我首先概要的介绍一下JTA。
JTA概要介绍
Java事务API(JTAJavaTransactionAPI)和它的同胞Java事务服务(JTSJavaTransactionService),为J2EE平台提供了分布式事务服务。
一个分布式事务(distributedtransaction)包括一个事务管理器(transactionmanager)和一个或多个资源管理器(resourcemanager)。
一个资源管理器(resourcemanager)是任意类型的持久化数据存储。
事务管理器(transactionmanager)承担着所有事务参与单元者的相互通讯的责任。
下车站显示了事务管理器和资源管理的间的关系。
JTA事务比JDBC事务更强大。
一个JTA事务可以有多个参与者,而一个JDBC事务则被限定在一个单一的数据库连接。
下列任一个Java平台的组件都可以参与到一个JTA事务中:
.JDBC连接
.JDOPersistenceManager对象
.JMS队列
.JMS主题
.企业JavaBeans(EJB)
.一个用J2EEConnectorArchitecture规范编译的资源分配器。
使用JTA的事务划分
要用JTA来划分一个事务,应用程序调用javax.transaction.UserTransaction接口中的方法。
示例4显示了一个典型的JNDI搜索的UseTransaction对象。
importjavax.transaction.*;
importjavax.naming.*;
//...
InitialContextctx=newInitialContext();
ObjecttxObj=ctx.lookup("java:
comp/UserTransaction");
UserTransactionutx=(UserTransaction)txObj;
应用程序有了UserTransaction对象的引用之后,就可以象示例5那样来起动事务。
utx.begin();
//...
DataSourceds=obtainXADataSource();
Connectionconn=ds.getConnection();
pstmt=conn.prepareStatement("UPDATEMOVIES...");
pstmt.setString(1,"SpinalTap");
pstmt.executeUpdate();
//...
mit();
//...
当应用程序调用commit()时,事务管理器使用两段提交协议来结束事务。
JTA事务控制的方法
.javax.transaction.UserTransaction接口提供了下列事务控制方法:
.publicvoidbegin()
.publicvoidcommit()
.publicvoidrollback()
.publicvoidgetStatus()
.publicvoidsetRollbackOnly()
.publicvoidsetTransactionTimeout(int)
应用程序调用begin()来起动事务,即可调用commit()也可以调用rollback()来结束事务。
使用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.Cmit()或java.sql.Connection.rollback()。
相反,应用程序应该使用UserTransaction.begin()、UserTmit()和UserTransaction.rollback().
选择最好的方法
我们已经讨论了JDBC和JTA是怎样划分事务的。
每一种方法都有它的优点,回此你需要决定为你的应用程序选择一个最适应的方法。
在我们团队许多最近的对于事务划分的项目中使用JDBCAPI来创建DAO类。
这DAO类总结如下:
.事务划分代码被嵌入到DAO类内部
.DAO类使用JDBCAPI来进行事务划分
.调用者没有划分事务的方法
.事务范围被限定在一个单一的JDBC连接
JDBC事务对复杂的企业应用程序不总是有效的。
如果你的事务将跨越多个DAO对象或
多个数据库,那么下面的实现策略可能会更恰当。
:
.用JTA对事务进行划分
.事务划分代码被DAO分开
.调用者承担划分事务的责任
.DAO参与一个全局的事务中
JDBC方法由于它的简易性而具有吸引力,JTA方法提供了更多灵活性。
你选择什么样的实现将依赖于你的应用程序的特定需求。
日志记录和DAO
一个好的DAO实现类将使用日志记录来捕获有关它在运行时的行为细节。
你可以选择记录异常、配置信息、连接状态、JDBC驱动程序的元数据或查询参数。
日志对开发整个阶段都是有益的。
我经常检查应用程序在开发期间、测试期间和产品中的日志记录。
在这段中,我们将展现一段如何把JakartaCommaonsLogging结合中一个DAO中的例子。
在我们开始之前,让我们先回顾一些基础知识。
选择一个日志例库
许多开发人员使用的基本日志形式是:
System.out.println和System.err.println.Println语句。
这种形式快捷方便,但它们不能提供一个完整的日志系统的的能力。
下表列出了Java平台的日志类库:
日志类库开源吗?
URL
Java.util.logging否
JakartaLog4j是http:
//hajarta.apache.org/log4j/
JakartaCommonsLogging是http:
/Jakarta.apache.org/commons/logging.html
Java.util.logging是J2SE1.4平台上的标准的API。
但是,大多数开发人员都认为JakartaLog4j提供了更大的功能性和灵活性。
Log4j超越java.util.logging的优点之一就是它支持J2SE1.3和J2SE1.4平台。
JakartaCommonsLogging能够被用于和java.util.loggin或JakartaLog4j一起工作。
CommonsLogging是一个把你的应用程序独立于日志实现的提取层。
使用CommonsLogging你能够通过改变一个配置文件来与下面的日志实现来交换数据。
CommonsLogging被用于JAKARTAStruts1.1和JakartaHttpClient2.0中。
一个日志示例
示例7显示了在一个DOA类中怎样使用JakartaCommonsLogging
importmons.logging.*;
classDocumentDAOImplimplementsDocumentDAO
{
staticprivatefinalLoglog=LogFactory.getLog(DocumentDAOImpl.class);
publicvoiddeleteDocument(Stringid)
{
//...
log.debug("deletingdocument:
"+id);
//...
try
{
//...dataoperations...
}
catch(SomeExceptionex)
{
log.error("Unabletodeletedocument",ex);
//...handletheexception...
}
}
}
日志是评估应用程序的基本部分。
如果你在一个DAO中遇到了失败,日志经常会为理解发生的什么错误提供最好的信息。
把日志结合到你的DAO中,确保得到调试和解决问题的有效手段。
DAO中的异常处理
我们已经看了事务划分和日志记录,并且现在对于它们是怎样应用于数据访问对象的有一个深入的理解。
我们第三部分也是最后要讨论的是异常处理。
下面的一些简单的异常处理方针使用你的DAO更容易使用,更加健壮和更具有可维护性。
在实现DAO模式的时候,要考滤下面的问题:
.在DAO的public接口中的方法将抛出被检查的异常吗?
.如果是,将抛出什么样的检查性异常?
.在DAO实现类中怎能样处理异常。
在用DAO模式工作的过程中,我们的团队为异常处理开发了一组方针。
下面的这些方针会很大程度的改善你的DAO:
.DAO方法应该抛出有意义的异常。
.DAO方法不应该抛出java.lang.Exception异常。
因为java.lang.Exception太一般化,它不能包含有关潜在问题的所有信息。
.DAO方法不应该抛出java.sql.SQLException异常。
SQLException是一个底层的JDBC异常,DAO应用努力封装JDBC异常而不应该把JDBC异常留给应用程序的其它部分。
.在DAO接口中的方法应该只抛出调用者期望处理的检查性异常。
如果调用者不能用适当的方法来处理异常,考滤抛出不检查性(运行时run-time)异常。
.如果你的数据访问代码捕获了一个异常,不可要忽略它。
忽略捕获异常的DAO是很处理的。
.使用异常链把底层的异常传递给高层的某个处理器。
.考滤定义一个标准的DAO异常类。
Spring框架提供了一个优秀的预定义的DAO异常类的集合。
看Resources,查看有异常和异常处理技术的更详细信息。
实现示例:
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的数据操作。
这个接口有如下五个方法:
.publicMoviefindMovieById(Stringid)
.publicjava.util.CollectionfindMoviesByYear(Stringyear)
.publicvoiddeleteMovie(Stringid)
.publicMoviecreateMovie(Stringrating,Stringyear,Stringtitle)
.publicvoidupdateMovie(Stringid,Stringrating,Stringyear,Stringtitle)
daoexamples.movie包包含了两个MovieDAO接口的实现。
每个实现使用了一个同的事务划分方法,如下表所示:
MovieDAOImplMovieDAOImplJTA
实现了MovieDAO接口吗?
YesYes
通过JNDI获得DataSource吗?
YesYes
从一个DataSource获得java.sql.Connection对象吗?
YesYes
DAO界定内部的事务吗?
YesNo
使用JDBC事务吗?
YesNo
使用一个XADataSource吗?
NoYes
分担JTA事务吗?
NoYes
MovieDAO示范应用程序
这个示范应用程序是一个叫做daoexamples.moviedemo.DemoServlet.DemoServlet的servlet类,它使用MovieDAO来查询和更新一个表中的movie数据。
这个servlet示范了把JTA感知的MovieDAO和Java消息服务组合到一个单一的事务中,如示例8所示:
UserTransactionutx=MovieUtil.getUserTransaction();
utx.begin();
batman=dao.createMovie("R",
"2008",
"BatmanReloaded");
publisher=newMessagePublisher();
publisher.publishTextMessage("I'llbeback");
dao.updateMovie(topgun.getId(),
"PG-13",
topgun.getReleaseYear(),
topgun.getTitle());
dao.deleteMovie(legallyblonde.getId());
mit();
要运行这个范例应用程序,在你的应用程序服务器中配置一个XA数据源和一个非XA数据源。
然后布署daoexamples.ear文件。
这个应用程序将运行在任何与J2EE兼容的应用程序服务器。
DAO解决了JSP页面维护难的问题,使JSP不能用JAVA.SQL.*所有的数据库代码用PreapreStatemnet,hirnate,ibait的来做
DAO属于J2EE数据库的操作,
它封装了一个项目的所有的数据库操作
所有的
客户---VO----DAO
VO对象和表中的字段完全对于
查询全部是返回LIST,所需要用Iterator来进行输出
importjava.util.*;
importcn.mldn.lxh.vo.*;
//规定出了操作person表在此项目里的全部方法
publicinterfacePersonDAO
{
//增加操作
publicvoidinsert(Personperson)throwsException;
//修改操作
publicvoidupdate(Personperson)throwsException;
//删除操作
publicvoiddelete(Stringid)throwsException;
//按ID查询操作
publicPersonqueryById(Stringid)throwsException;
//查询全部
publicListqueryAll()throwsException;
//模糊查询
publicListqueryByLike(Stringcond)throwsException;
}
packagecn.mldn.lxh.dao.impl;
importjava.sql.*;
importjava.util.*;
importcn.mldn.lxh.vo.*;
importcn.mldn.lxh.dbc.*;
importcn.mldn.lxh.dao.*;
//此类需要完成具体的数据库操作,需要JDB代码
publicclassPersonDAOImplimplementsPersonDAO
{
//增加操作
publicvoidinsert(Personperson)throwsException
{
Stringsql="INSERTINTOperson(id,name,password,age,email)VALUES(?
?
?
?
?
)";
PreparedStatementpstmt=null;
DataBaseConnectiondbc=null;
//下面是针对数据库的具体操作
try
{
//连接数据库
dbc=newDataBaseConnection
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- java dao