用ThreadLocal管理事务

1、适用场景

一个service,操作两个dao,要求两个dao为同一个事务,要么全成功,要么全失败。

DBUtils,使用ThreadLocal

 1 public class DbUtils {
 2     //线程局部数据容器
 3     private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();    
 4     private static DataSource ds;
 5     private static Connection conn;    
 6     static{
 7         ds=new ComboPooledDataSource();
 8     }
 9     
10     public static DataSource getdDataSource()
11     {
12         return ds;
13     }    
14     public static Connection getcConnection()
15     {
16         
17         try {            
18             conn=tl.get();//是否已经有值
19             if(conn==null)//没有值就添加
20             {
21                 conn=ds.getConnection();
22                 tl.set(conn);
23             }
24             
25         } catch (SQLException e) {
26             e.printStackTrace();
27         }
28         return conn;
29     }
30     
31     public static void remove()
32     {
33         tl.remove();//实现一个删除thredlocal中与线程相关的对象
34     }    
35 }

过滤器中管理事务

 1 public void doFilter(ServletRequest request, ServletResponse response,
 2             FilterChain chain) throws IOException, ServletException {
 3         Connection conn = null;
 4         try {
 5             conn = DbUtils.getcConnection();
 6             conn.setAutoCommit(false);
 7             chain.doFilter(request, response);//放行
 8             conn.commit();//如果没有出错,提交事务,所以需要在dao中抛出异常,不能try-catch,否则无法捕捉到错误
 9             System.err.println("成功.......................");
10         } catch (Exception e) {
11             System.err.println("出错了......................");
12             try {
13                 //判断是否是数据库错误,如果不是还是提交
14                 if (e instanceof SQLException) {
15                     conn.rollback();
16                 } else {
17                     conn.commit();
18                 }
19             } catch (SQLException e1) {
20                 e1.printStackTrace();
21             }
22         } finally {
23             try {
24                 conn.close();//关闭连接
25                 DbUtils.remove();//实现一个删除thredlocal中与线程相关的对象
26             } catch (SQLException e) {
27                 e.printStackTrace();
28             }
29         }
30     }

注意:必须在dao中抛出异常,否则无法捕捉到,永远是提交事务。

 dao层:

try {
                DataSource ds=DbUtils.getdDataSource();
                Connection conn=ds.getConnection();
                QueryRunner run =new QueryRunner(ds);
                String sql="INSERT INTO users VALUES (?,?,? ";
                run.update(conn, sql,"U005","Tom","456");
            } catch (SQLException e) {                
                throw new RuntimeException(e);
            }

如果需要进行事务的管理,添加到过滤器url中即可

原文地址:https://www.cnblogs.com/liuwt365/p/4129585.html