用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中即可