设为首页 加入收藏

TOP

通向架构师的道路(第七天)之漫谈使用 ThreadLocal 改进你的层次的划分(二)
2018-02-06 13:13:05 】 浏览:982
Tags:通向 架构 师的 道路 漫谈 使用 ThreadLocal 改进 层次 划分
是?我们只管写dao方法,service方法,不需要关心在哪边commit哪边rollback何时connection,spring的声明式事务会帮我们负责,这种风格我们称为“优雅”,各层间耦合度极大程度上的降低,封装性好。

因此,我们可以总结出下面这些好处:

  • Service层的方法只管开启事务(如果讲究点的还会设一个Transaction);
  • 在该Service层中的所有dao使用该service方法中开启的事务(即connection);
  • Dao中每次只管getCurrentConnection(获取当前的connection),与进行数据处理
  • Dao层中如果发生错误就抛回Service层
  • Service层中接到exception,在catch{}中rollback,在try{}未尾commit,在finally块中关闭整个connection。

这。。。就是我们所说的ThreadLocal。

举个更实际的例子再次来说明ThreadLocal:

我们有3个用户访问同一个service方法,该service方法内有3个dao方法为一个完整事务,那么整个web容器内只因该有3个connection,并且每个connection之间的状态,彼此“隔离”。

我们下面一起来看我们如何用代码实现类似于Spring的这种做法。

首先,根据我们的ThreadLocal的概念,我们先声明一个ConnectionManager的类。

2.4 利用ThreadLocal制作ConnectionManager

public class ConnectionManager {

         private static ThreadLocal tl = new ThreadLocal();

         private static Connection conn = null;

         public static void BeginTrans(boolean beginTrans) throws Exception {

                   if (tl.get() == null || ((Connection) tl.get()).isClosed()) {

                            conn = SingletonDBConnection.getInstance().getConnection();

                            conn = new ConnectionSpy(conn);

                            if (beginTrans) {

                                     conn.setAutoCommit(false);
                            }
                            tl.set(conn);
                   }

         }

         public static Connection getConnection() throws Exception {
                   return (Connection) tl.get();

         }

         public static void close() throws SQLException {

                   try {

                            ((Connection) tl.get()).setAutoCommit(true);

                   } catch (Exception e) {

                   }

                   ((Connection) tl.get()).close();

                   tl.set(null);

         }

         public static void commit() throws SQLException {

                   try {
                            ((Connection) tl.get()).commit();
                   } catch (Exception e) {

                   }

                   try {

                            ((Connection) tl.get()).setAutoCommit(true);

                   } catch (Exception e) {
                   }
         }

         public static void rollback() throws SQLException {

                   try {

                            ((Connection) tl.get()).rollback();
                   } catch (Exception e) {

                   }

                   try {

                            ((Connection) tl.get()).setAutoCommit(true);

                   } catch (Exception e) {

                   }
         }
}

2.5 利用ThreadLocal改造Service与Dao层

Service层(注意红色标粗-好粗yeah,的地方)

package sky.org.service.impl;

public class StudentServiceImpl implements StudentService {

         public void addStudent(Student std) throws Exception {

                   StudentDAO studentDAO = new StudentDAOImpl();
                   ClassRoomDAO classRoomDAO = new ClassRoomDAOImpl();

                   try {
                            ConnectionManager.BeginTrans(true);
                            studentDAO.addStudent(std);
                            classRoomDAO
                                              .addStudentClassRoom(std.getClassRoomId(), std.getsNo());

                            ConnectionManager.commit();

                   } catch (Exception e) {

                            try {
                                     ConnectionManager.rollback();
                            } catch (Exception de) {
                            }

                            throw new Exception(e);

                   }finally {

                            try {
                                     ConnectionManager.close();

                            } catch (Exception e) {

                           }
                   }
         }
}

Look,如果我把上述标粗(没有加红色)的地方,全部用AOP的方式从这块代码的外部“切”进去。。。是不是一个Spring里的Service方法就诞生了?

下面来看一个完整的例子

2.6 使用ThreadLocal分离Service、DAO层

先来看表结构:

T_Student表

T_ClassRoom表

T_Student_ClassRoom表

需求:

很简单,T_ClassRoom表里已经有值了,在插入T_Student表的数据时同时要给这个学生分配一个班级并且插入T_Student_ClassRoom表,这就是一个事务,这两步中有任何一步出错,事务必须回滚。

看来工程的结构吧:

下面开始放出所有源代码:

2.6.1 ConnectionManager类

package sky.org.util.db;

import java.sql.*;

public class ConnectionManager {

         private static ThreadLocal tl = new ThreadLocal();

         private static Connection conn = null;

         public static void BeginTrans(boolean beginTrans) throws Exception {
首页 上一页 1 2 3 4 5 6 7 下一页 尾页 2/8/8
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇大数据搜索选开源还是商业软件?E.. 下一篇记一次 MySQL 删库的数据恢复

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目