`
yiding_he
  • 浏览: 446148 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类
最新评论

DAO 设计4、事务处理(1)

阅读更多
事务的处理从来都是“三部曲”:
java 代码
  1. try {
  2.     begin();
  3.     // ...
  4.     commit();
  5. } catch (Exception e) {
  6.     rollback();
  7. }

在 JDBC 中,调用事务处理并不复杂,因为 Connection 类提供了现成的方法,就是 setAutoCommit() 、commit() 和 rollback()。

我们希望 DAO 能够在这个基础上更加方便的处理事务:每个线程都执行各自的事务,一旦事务开始,线程中所有的 DAO 对象的操作都将处于该事务当中,随同事务一起提交和回滚,这样就能大大简化当一个事务需要连接多个数据库时的处理方式。

每个线程执行各自的事务,这同数据库本身处理事务的方式是一致的,不需要特别设计。另外每个线程还需要有各自的标识说明当前事务状态,用 ThredLocal 就可以了。

首先给 DAO 类增加事务处理的静态方法:
DAO.java
  1. /**
  2. * 开始事务
  3. *
  4. * @throws DAOException 如果读取配置或执行数据库失败
  5. */
  6. public static void beginTransaction() throws DAOException {
  7.     try {
  8.         log.debug("事务开始。");
  9.         GlobalTransaction.begin();
  10.     } catch (Exception e) {
  11.         throw new DAOException(e);
  12.     }
  13. }
  14. /**
  15. * 提交事务
  16. *
  17. * @throws DAOException 如果执行数据库失败
  18. */
  19. public static void commitTransaction() throws DAOException {
  20.     // 如果不在事务当中则不做任何操作
  21.     if (!GlobalTransaction.isInTransaction()) {
  22.         return;
  23.     }
  24.     try {
  25.         GlobalTransaction.commit();
  26.     } catch (Exception e) {
  27.         throw new DAOException(e);
  28.     }
  29. }
  30. /**
  31. * 回滚事务
  32. *
  33. * @throws DAOException 如果回滚失败
  34. */
  35. public static void rollbackTransaction() throws DAOException {
  36.     // 如果不在事务当中则不做任何操作
  37.     if (!GlobalTransaction.isInTransaction()) {
  38.         return;
  39.     }
  40.     try {
  41.         GlobalTransaction.rollbackFinish();
  42.     } catch (Exception e) {
  43.         throw new DAOException(e);
  44.     }
  45. }

可以看出,这几个方法都允许连续调用多次,但实际上只有第一次起了作用。

我们争论过是否实现“事务嵌套”。但实际上根据事务的定义,事务不存在“嵌套”的说法。想一想,如果“子事务”被 rollback 掉了,那么因为它执行不成功,“父事务”也必然会被 rollback 掉,否则就不叫事务了。这跟在同一个事务里没有区别。JDBC 也没有所谓“事务嵌套”的概念。

当事务开始之后,持有 Connection 的 DbExecutor 对象必须被缓存起来以供下次调用。它们被缓存在 GlobalTransaction 中(见下图)。一旦事务结束,GlobalTransaction 便会将线程中缓存的 DbExecutor 对象全部清掉。



DbExecutorFactory.java
  1. /**
  2. * 创建 DbExecutor 对象
  3. *
  4. * @param dsName 数据源名称
  5. *
  6. * @return 连接到指定数据源的 DbExecutor 对象。如果当前处于事务中,则从事务缓存中获取 DbExecutor 对象,否则重新创建一个。
  7. *
  8. * @throws ConfigErrorException 如果读取配置失败
  9. * @throws DAOException 如果获取数据库连接失败
  10. */
  11. public DbExecutor getDbExecutor(String dsName) throws ConfigErrorException, DAOException {
  12.     try {
  13.         DbExecutor executor = GlobalTransaction.getExecutor(dsName);
  14.         if (executor == null || executor.isClosed()) {
  15.             log.debug("重新创建executor \"" + dsName + "\"");
  16.             executor = createNewExecutor(dsName);

  17.             if (GlobalTransaction.isInTransaction()) {
  18.             // 将获得的 DbExecutor 对象放入事务缓存
  19.                 executor.beginTransaction();
  20.                 GlobalTransaction.saveExecutor(dsName, executor);
  21.             }
  22.         }
  23.         return executor;
  24.     } catch (SQLException e) {
  25.         throw new DAOException(e);
  26.     }
  27. }
GlobalTransaction.java
 
  1. /** 
  2.  * 获得当前线程内缓存的连接到指定数据源的 DbExecutor 对象 
  3.  * 
  4.  * @param dsName 数据原名称 
  5.  * 
  6.  * @return 如果数据源处于事务当中,则返回正在处理该事务的 DbExecutor,否则返回 null 
  7.  */  
  8. public static DbExecutor getExecutor(String dsName) {  
  9.     HashMap map = getExecutorsMap();  
  10.     return (DbExecutor) map.get(dsName);  
  11. }  
  12.   
  13. /** 
  14.  * 开始事务 
  15.  */  
  16. public static void begin() {  
  17.     status.set(STARTED);  
  18. }  
  19.   
  20. /** 
  21.  * 提交事务 
  22.  */  
  23. public static void commit() {  
  24.     HashMap map = getExecutorsMap();  
  25.     Collection executors = map.values();  
  26.     for (Iterator iterator = executors.iterator(); iterator.hasNext();) {  
  27.         DbExecutor executor = (DbExecutor) iterator.next();  
  28.         executor.close();  
  29.     }  
  30.     map.clear();  
  31.     status.set(FINISHED);  
  32. }  
  33.   
  34. /** 
  35.  * 回滚事务 
  36.  */  
  37. public static void rollback() {  
  38.     if (!getStatus().equals(STARTED)) {  
  39.         return;  
  40.     }  
  41.   
  42.     Collection executors = ((HashMap) transactions.get()).values();  
  43.     for (Iterator iterator = executors.iterator(); iterator.hasNext();) {  
  44.         DbExecutor executor = (DbExecutor) iterator.next();  
  45.         try {  
  46.             executor.rollback();  
  47.         } catch (SQLException e) {  
  48.             log.error("事务回滚失败", e);  
  49.         }  
  50.     }  
  51.     getExecutorsMap().clear();  
  52.     status.set(ROLLBACKED);  
  53. }  


同时,DAO 对象在每次执行完数据库操作的时候,要判断一下当前是否处于事务当中。以 insert 方法为例:
DAO.java
  1. /**
  2. * 执行数据库插入
  3. *
  4. * @param obj 要插入的记录
  5. * @param tablename 要插入的表名
  6. *
  7. * @throws DAOException 如果读取配置或执行数据库失败
  8. */
  9. public void insert(Object obj, String tablename) throws DAOException {
  10.     DbExecutor executor = null;
  11.     try {
  12.         executor = initExecutor();
  13.         executor.insert(obj, tablename);
  14.     } catch (DAOException e) {
  15.          throw e;
  16.     } catch (Exception e) {
  17.          throw new DAOException(e);
  18.     } finally {
  19.         if (!GlobalTransaction.isInTransaction() && executor != null) {
  20.             executor.close();
  21.         }
  22.     }
  23. }


至此便实现了 DAO 对事务的处理。
分享到:
评论
5 楼 ahua3515 2007-04-08  
ok  多看些源代码应该会更有心得
4 楼 andyandyandy 2007-04-03  
写得不错
3 楼 jncz 2007-03-30  
http://www.iteye.com/post/177582
2 楼 cozone_柯中 2007-03-30  
killvirus 写道
学习了


一样
1 楼 killvirus 2007-03-30  
学习了

相关推荐

    DAO设计模式 DAO 设计模式 JAVA设计模式

    DAO(Data Access Object)设计模式是软件开发中一种常见的用于处理数据访问的模式,它将业务逻辑与数据访问逻辑分离,使得代码结构更加...因此,深入理解并灵活运用DAO设计模式对于提升Java应用程序的质量至关重要。

    Dao设计模式教程

    1. **DAO设计模式的概念** DAO设计模式是一种面向对象的设计模式,用于处理应用程序和数据存储之间的交互。它提供了一种方式来封装对底层数据源的操作,使得业务层代码无需直接与数据库进行交互,而是通过调用DAO...

    DAO设计模式DAO设计模式

    事务处理是DAO设计模式中的一个关键组成部分。事务是指一组相关的操作序列,这些操作要么全部成功,要么全部失败。在DAO设计模式中,事务的管理至关重要,因为这关系到数据的一致性和完整性。 - **事务划分**:决定...

    dao设计模式DAO 设计模式之事务界定疯.pdf

    ### DAO设计模式与事务管理 #### 一、引言 在软件开发中,尤其是在基于数据库的应用程序中,数据访问层(Data Access Object, DAO)设计模式是一种常用的模式,用于简化和标准化对数据库的操作。该模式的主要目的...

    DAO设计模式辅助资料

    4. **事务管理**:在DAO实现中,通常需要处理事务管理。比如,当一个操作涉及多条数据库记录时,需要在一个事务中执行,以确保数据一致性。 5. **异常处理**:DAO层应该捕获并封装数据库操作可能抛出的异常,向上层...

    DAO设计模式(工厂+代理)

    在DAO设计模式中,代理可以用来添加额外的功能,比如事务管理、日志记录等,而这些功能并不属于原始DAO的职责。代理类通常会持有真实DAO的引用,并在调用其方法之前和之后执行额外的操作。 例如: ```java public ...

    JAVA_DAO 事务界定 异常处理,日志记录

    综上所述,在 DAO 设计中,事务界定、异常处理和日志记录是非常重要的组成部分。通过合理地设计和实现这些功能,可以大大提高应用程序的健壮性和可维护性。开发者应该根据实际需求选择合适的事务界定策略,并确保...

    JAVA设计模式之事务处理

    在讨论事务处理的设计时,通常推荐将事务管理置于服务层,而不是DAO层。这是因为业务服务层通常代表一个完整的业务操作,它可能需要调用多个DAO来完成任务。例如,在一个简单的网上书店购书场景中,`...

    DAO设计模式Demo

    总结来说,DAO设计模式是软件工程中用于处理数据访问的重要模式,它提高了代码的可复用性和可维护性,同时通过接口隔离了业务逻辑和数据操作的细节。在Java开发中,DAO模式常常结合JDBC或其他ORM框架实现,以实现对...

    JavaWeb DAO设计模式DEMO

    这个"JavaWeb DAO设计模式DEMO"是一个示例项目,旨在帮助初学者理解并掌握DAO模式的实现。 DAO模式的主要目标是创建一个独立于数据库访问的接口,这样业务逻辑组件就可以通过这个接口来操作数据,而不需要知道具体...

    dao设计模式视频教程

    在本"DAO设计模式视频教程"中,你将深入理解这种模式的核心概念、应用场景以及实现方式。 DAO模式的主要目标是创建一个独立于数据库访问的接口层,使得业务对象可以不直接与数据库进行交互,而是通过调用DAO对象的...

    DAO设计模式.rar

    4. **事务管理**:在进行数据库操作时,特别是涉及多表操作或需要确保数据一致性的场景,事务管理是必不可少的。这可能涉及到Spring的Transaction API,用来控制事务的开始、提交、回滚等操作。 5. **异常处理**:...

    DAO设计模式设计一个论坛

    在这个“DAO设计模式设计论坛”的项目中,我们将探讨如何使用DAO模式来构建一个论坛系统。 首先,DAO模式的核心思想是创建一个独立的数据访问对象,这个对象负责与数据库进行交互,执行CRUD(Create、Read、Update...

    DAO设计模式精讲(java web开发)

    在本精讲中,我们将深入探讨DAO设计模式的原理、实现方式以及在实际项目中的应用。 **DAO设计模式的核心思想** DAO设计模式的核心是创建一个接口,该接口定义了对数据库进行操作的方法,如查询、插入、更新和删除...

    初步认识JAVA DAO设计模式

    总结来说,DAO设计模式在Java开发中扮演着重要的角色,尤其是在处理数据持久化问题时,它提供了一种灵活且可扩展的方式来管理数据访问,降低了系统的复杂性,提高了代码的可维护性。通过将数据访问逻辑封装在DAO中,...

    Java Dao设计模式操作数据库

    4. **异常处理**:在DAO实现中,我们需要捕获并适当地处理JDBC抛出的异常,如`SQLException`。通常,我们会将这些异常转化为自定义的业务异常,以便上层业务代码可以更好地理解问题所在。 5. **资源释放**:为了...

    DAO 设计模式经典实例

    DAO设计模式的主要目标是创建一个接口,该接口负责处理数据存储和检索的底层细节。通过这种方式,业务逻辑层可以与具体的数据存储机制解耦。DAO对象通常会封装SQL查询或者NoSQL操作,提供一套面向对象的方法来操作...

    web学习笔记 —— DAO设计模式

    通过阅读《318_DAO设计模式.pdf》这份文档,你可以深入理解DAO模式的原理、实现方式以及在Web开发中的应用。同时,文档可能还会介绍一些相关的工具和技术,如MyBatis的使用、Spring的AOP事务管理等,这些都是DAO模式...

Global site tag (gtag.js) - Google Analytics