ThreadLocal-------结合Filter用于管理Web开发中数据库的事务

1、利用 ThreadLocal和Filter,管理Web开发中数据库事务的原理图解

      

2、TransactionFilter的实现    

      2.1  关于事务Filter的讲解

      对于事务相关的Filter,应该在请求的路径,里面含数据库的操作时,才会开启事务。如果访问的是静态资源,例如,1.png就不应该开启事务。所以事务的开启,不是一进入到Filter就开启事务。因为,如果一进入到Filter就开启事务,这样的话请求静态资源,也会开启事务。所以将事物的开启,放到获取数据库的连接Connection时,才开启事务。也就是,只有在进行数据库相关操作时,才会开启事务。因为数据库的连接Connection,是放在ThreadLocal中的,所以第二个DAO获取的数据库连接Connection,也就是第一个DAO已经开启事务的连接。关于数据库连接Connection的管理,见JdbcUtils.java的实现。并且在Filter的最后,应该关闭连接,释放资源。

     2.2 关于事务的执行

           当在Service或者Servlet中,抛出运行时异常,那么Filter中,public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {}方法里面,在chain.doFilter(request, response)后面的语句,将不会执行。

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import cn.itcast.utils.JdbcUtils;
public class TransactionFilter implements Filter {
	public void destroy() {
	}
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		// index.jsp dao dao
		// 1.jpg
		try {
			System.out.println("进入了事务拦截器");
			// 1.拦截下来后:获取连接、开启事务、并把连接绑定到当前线程
			// 1.1对于静态资源,不拦截;只有涉及到数据库操作时,才开启事务的管理。
			// 1.2对于dao操作数据库时,在JdbcUtils.getConnection()时,会自动开启事务
			// JdbcUtils.getConnection();
			// JdbcUtils.StartTransaction();

			chain.doFilter(request, response);
			// 2.目标资源执行 dao1 conn1 = JdbcUtils.getConnection();
			// dao2 conn2 = JdbcUtils.getConnection() 因为ThreadLoca,conn2就是上面开启事务的连接
			// 3.获取当前线程上绑定的连接,提交事务,并关闭链接,释放连接与当前线程的绑定
			System.out.println("关闭事务");
			JdbcUtils.commitTransaction();
		} finally {
			JdbcUtils.closeConn();
		}

	}
	public void init(FilterConfig filterConfig) throws ServletException {
	}
}

3、利用ThreadLocal来管理,数据库连接池的实现

import java.sql.Connection;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
 * <pre>
 * 用于保证一个请求,用一个数据库的Connection
 * 再结合,事务拦截器,用于做事务管理
 * </pre>
 * 
 */
public class JdbcUtils {
	/**
	 * <pre>
	 * 用于保证一个请求,用一个数据库的Connection
	 * 再结合,事务拦截器,用于做事务管理
	 * </pre>
	 * 
	 */
	private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
	/**
	 * 数据库的数据源
	 */
	private static DataSource ds;
	/**
	 * 使用c3p0初始化,数据库连接源
	 */
	static {
		ds = new ComboPooledDataSource();
	}

	public static DataSource getDataSource() {
		return ds;
	}

	/**
	 * 获取和当前线程先关的数据库连接Connection
	 * 
	 * @return
	 */
	public static Connection getConnection() {
		try {
			Connection conn = tl.get();
			if (conn == null) {
				conn = ds.getConnection();
				// 自己管理事务
				conn.setAutoCommit(false);
			}
			tl.set(conn);
			return conn;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 手动的开启事务
	 */
	public static void StartTransaction() {
		try {
			Connection conn = getConnection();
			// 自己管理事务,开启事务
			conn.setAutoCommit(false);

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 手动的提交事务
	 */
	public static void commitTransaction() {
		try {
			Connection conn = getConnection();
			if (conn != null) {
				// 关闭事务
				conn.commit();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 手动的回滚
	 */
	public static void rollbackTransaction() {
		try {
			Connection conn = getConnection();
			if (conn != null) {
				// 回滚事务
				conn.rollback();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 关闭连接,记得将ThreadLocal里面的Connection移除
	 */
	public static void closeConn() {
		Connection conn = null;
		try {
			conn = getConnection();
			if (conn != null) {
				conn.close();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			tl.remove();
		}
	}
}
4、Servlet中,对于异常的处理

     

5、源码下载


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值