利用ThreadLocal & Filter 实现事务处理

来源:互联网 发布:维尔迪数据 编辑:程序博客网 时间:2024/05/17 22:03

关于ThreadLocal

?      通过ThreadLocal.set()将对象的引用保存到各线程的自己的一个 map,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作为mapkey来使用的

?      一般情况下,通过ThreadLocal.set()到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的

?      ThreadLocal 不是用来解决共享对象的多线程访问问题的:如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的 ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。

?      ThreadLocal的应用场合:按线程多实例(每个线程对应一个实例)的对象的访问。

 

 

ThreadLocalContext.java

package com.sherman.bookstore.web;

 

import java.sql.Connection;

 

publicclass ThreadLocalContext {

    private ThreadLocal<Connection>connectionThreadLocal =new ThreadLocal<>();

    privatestatic ThreadLocalContextinstance =newThreadLocalContext();

    private ThreadLocalContext(){}

    publicstatic ThreadLocalContext getInstance(){

       returninstance;

    }

    publicvoid bind(Connectionconnection){

       connectionThreadLocal.set(connection);

    }

   

    public Connection getConnetion(){

       returnconnectionThreadLocal.get();

    }

   

    publicvoid remove(){

       connectionThreadLocal.remove();

    }

}

TransactionFilter.java

package com.sherman.bookstore.filter;

import java.io.IOException;

import ……;

import com.sherman.bookstore.db.JDBCUtils;

import com.sherman.bookstore.web.ThreadLocalContext;

 

/**

 *Servlet Filter implementation classTransactionFilter

 */

@WebFilter("/*")

publicclass TransactionFilterimplements Filter {

    public TransactionFilter() {

        //TODO Auto-generated constructor stub

    }

    publicvoid destroy() {

       //TODO Auto-generatedmethod stub

    }

    /**

     *@seeFilter#doFilter(ServletRequest, ServletResponse, FilterChain)

     */

    publicvoid doFilter(ServletRequestrequest, ServletResponseresponse, FilterChainchain)throws IOException,ServletException {

       Connectionconnection =null;

       try {

           //1. 获取连接

           connection = JDBCUtils.getConnection();

           //2. 开启事务

           connection.setAutoCommit(false);

           //3. 利用 ThreadLocal把当前线程与数据库连接绑定

           ThreadLocalContext.getInstance().bind(connection);

           //4. 把请求转发给对应的Servlet

           chain.doFilter(request,response);

           //5. 提交事务

           connection.commit();

       } catch (Exceptione) {

           //6. 捕获异常,回滚事务,跳转至错误页面

           e.printStackTrace();

           try {

              connection.rollback();

           } catch (SQLExceptione1) {

              e1.printStackTrace();

           }

           HttpServletRequestreq = (HttpServletRequest)request;

           HttpServletResponseresp = (HttpServletResponse)response;

           resp.sendRedirect(req.getContextPath() + "/error-1.jsp");

       }finally{

           //7. 解除绑定

           ThreadLocalContext.getInstance().remove();

           //8. 关闭连接

           JDBCUtils.release(connection);

       }

    }

    publicvoid init(FilterConfigfConfig)throws ServletException{

       //TODO Auto-generatedmethod stub

    }

 

}

BaseDAO.java

package com.sherman.bookstore.dao.impl;

 

import java.lang.reflect.ParameterizedType;

import ……;

 

publicclass BaseDAO<T>implements DAO<T> {

    private QueryRunnerqueryRunner =new QueryRunner();

    private Class<T>genericType =null;

   

    @SuppressWarnings("unchecked")

    public BaseDAO(){

       Type type =this.getClass().getGenericSuperclass();

       if(typeinstanceof ParameterizedType){

           ParameterizedTypeparaType = (ParameterizedType)type;

           genericType = (Class<T>)paraType.getActualTypeArguments()[0];

       }

    }

   

    @Override

    publiclong insert(Stringsql, Object...args) {

       intid = 0;

      

       Connectionconn =null;

       PreparedStatementpsmt =null;

       ResultSet rs =null;

      

       try {

           conn = ThreadLocalContext.getInstance().getConnetion();

           psmt =conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);

           if(args != null){

              for (inti = 0;i <args.length;i++) {

                 psmt.setObject(i+1,args[i]);

              }

           }

           psmt.executeUpdate();

           rs =psmt.getGeneratedKeys();

           if(rs.next()){

              id =rs.getInt(1);

           }

       } catch (Exceptione) {

           thrownew DBException();

       } finally{

           JDBCUtils.release(rs,psmt);

       }

       returnid;

    }

 

    @Override

    publicvoid update(Stringsql, Object...args) {

       Connectionconn =null;

      

       try {

           conn = ThreadLocalContext.getInstance().getConnetion();

           queryRunner.update(conn,sql,args);

       } catch (Exceptione) {

           thrownew DBException();

       }

    }

 

    @Override

    public T query(Stringsql, Object...args) {

       T entity =null;

       Connectionconn =null;

      

       try {

           conn = ThreadLocalContext.getInstance().getConnetion();

           entity =queryRunner.query(conn,sql,new BeanHandler<>(genericType),args);

          

       } catch (Exceptione) {

           thrownew DBException();

       }

       returnentity;

    }

 

    @Override

    public List<T> queryForList(Stringsql, Object...args) {

       List<T> entityList =null;

       Connectionconn =null;

      

       try {

           conn = ThreadLocalContext.getInstance().getConnetion();

           entityList =queryRunner.query(conn,sql,new BeanListHandler<>(genericType),args);

          

       } catch (Exceptione) {

           thrownew DBException();

       }

       returnentityList;

    }

 

    @Override

    public <V> V getSingleVal(Stringsql, Object...args) {

       Connectionconn =null;

      

       try {

           conn = ThreadLocalContext.getInstance().getConnetion();

           returnqueryRunner.query(conn,sql,new ScalarHandler<V>(),args);

       } catch (Exceptione) {

           thrownew DBException();

       }

    }

 

    @Override

    publicvoid batch(Stringsql, Object[]...params) {

       Connectionconn =null;

      

       try {

           conn = ThreadLocalContext.getInstance().getConnetion();

           queryRunner.batch(conn,sql,params);

       } catch (Exceptione) {

           thrownew DBException();

       }

    }

 

}

 

0 0
原创粉丝点击