基于Filter和ThreadLocal实现事务管理

ThreadLocal类的作用

ThreadLocal 它可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组,集合)
ThreadLocal 的作用,它可以解决多线程的数据安全问题。
ThreadLocal 的特点:
1、ThreadLocal 可以为当前线程关联一个数据。(它可以像 Map 一样存取数据,key 为当前线程)
2、每一个 ThreadLocal 对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个 ThreadLocal 对象实例。
3、每个 ThreadLocal 对象实例定义的时候,一般都是 static 类型
4、ThreadLocal 中保存数据,在线程销毁后。会由 JVM 虚拟自动释放。

前提:客户端发起一次请求进入Filter然后后进入Servlet然后调用Service层然后调用Dao层,这些操作都在同一线程完成,所以可以给这个线程绑定一个数据库连接对象
在这里插入图片描述

1.首先修改JDBC工具类绑定ThreadLocal

public static Connection getConnection(){
        Connection connection =ThreadConns.get();
        if (connection==null){//如果线程数据获取的连接为空
            try {
                connection=druidDataSource.getConnection();//从数据连接池获取一个连接
                connection.setAutoCommit(false);//关闭自动提交
                ThreadConns.set(connection);//设置这个连接到当前执行的线程
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        return connection;
    }


    public static void commitAndClose(){
        Connection connection = ThreadConns.get();
        if (connection!=null){//如果当前线程获取的连接不为null
            try {
                connection.commit();//提交数据库操做事务
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                try {
                    connection.close();//关闭连接
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
        ThreadConns.remove();//一定要remove当前线程的connection数据库连接对象,否则会出错,因为Tomcat底层使用了线程池技术
    }

    public static void rollbackAndClose(){
        Connection connection = ThreadConns.get();
        if (connection!=null){//如果当前线程获取的连接不为null
            try {
                connection.rollback();//提交数据库操做事务
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }finally {
                try {
                    connection.close();//关闭连接
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
        }
        ThreadConns.remove();//一定要remove当前线程的connection数据库连接对象,否则会出错,因为Tomcat底层使用了线程池技术
    }

2.有关于BaseDao数据更新的操作都要手动捕获抛出异常

 public Object queryForSingleObject(String sql,Object... args){
        Connection connection= JdbcUtils.getConnection();
        try {
             return queryRunner.query(connection,sql,new ScalarHandler(),args);
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);//把异常通通抛出给最后在filter统一捕获做事务管理
        }
    }

 public <T> T queryForOne(Class<T> clazz,String sql,Object... args){
        Connection connection= JdbcUtils.getConnection();
        try {
            return queryRunner.query(connection, sql, new BeanHandler<>(clazz), args);
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);//把异常通通抛出给最后在filter统一捕获做事务管理
        }
    }

3.service服务层和BaseServlet的异常也要抛出,这里只列出BaseServlet

public class  BaseServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");
        String action=req.getParameter("action");
        try {
            Method declaredMethod = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
            declaredMethod.invoke(this,req,resp);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);//把异常通通抛出给最后在filter统一捕获做事务管理
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
      doPost(req,resp);
    }
}

4.TransactionFilter拦截请求,并捕获异常进行事务管理

public class TransactionFilter  implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        try {
            filterChain.doFilter(servletRequest,servletResponse);
            JdbcUtils.commitAndClose();//没有异常则提交事务并关闭连接
        } catch (Exception e) {
            JdbcUtils.rollbackAndClose();//有异常则回滚并关闭连接
            e.printStackTrace();
        }
    }

    @Override
    public void destroy() {

    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值