• 事务管理


            当每个执行JDBC的类都需要执行回滚和提交的操作,如下:

             那么如果有的DAO成功提交,有的需要回滚。但是service的操作需要是一个整体,不能部分成功,部分失败。所以事务管理应该以业务层的方法为单位,而不能以DAO层的单精度方法为单位。

            所以应该将上图中的try...catch...语句执行的内容转到service中。但因为servlet对应一个service,service又被filter拦截,所以可以将事务提交转移到filter中,如下:

            Notations:DAO1、2、3中的数据库连接Connection需要同一个。因此需要ThreadLocal本地线程。里面有set和get方法,将Connection设置到线程中。

    OpenSessionFilter:

            先写一个开始、提交和回滚事务的工具类,如下所示:        

    1. public class TransManager {
    2. //本地线程存储连接方便各个DAO方法使用
    3. private static ThreadLocal threadLocal=new ThreadLocal();
    4. //开始事务
    5. public void startTrans() throws SQLException {
    6. this.getConnection().setAutoCommit(false);
    7. }
    8. //提交事务
    9. public void commitTrans() throws SQLException {
    10. this.getConnection().commit();
    11. //因为这里的提交和回滚函数都是在filter处理响应的时候才执行,所以要执行关闭连接的操作
    12. this.getConnection().close();
    13. }
    14. //回滚事务
    15. public void rollTrans() throws SQLException {
    16. this.getConnection().rollback();
    17. this.getConnection().close();
    18. }
    19. private Connection getConnection() throws SQLException{
    20. Connection con=threadLocal.get();
    21. if(con==null){
    22. //发现threadLocal里面没有connection,就获取并设置
    23. //放在threadLocal里面就是为了一个DAO调用后再给下一个调用
    24. con=DButil.getConnection();
    25. threadLocal.set(con);
    26. }
    27. return con;
    28. }
    29. }

             然后在Filter的doFilter方法中进行事务的管理      

    1. @Override
    2. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    3. TransManager tm=new TransManager();
    4. try {
    5. tm.startTrans();
    6. filterChain.doFilter(servletRequest,servletResponse);
    7. tm.commitTrans();
    8. } catch (SQLException e) {
    9. try {
    10. tm.rollTrans();
    11. } catch (SQLException ex) {
    12. ex.printStackTrace();
    13. }
    14. e.printStackTrace();
    15. }
    16. }

    ThreadLocal

            ThreadLocal的set(obj)方法。源码如下:    

    1. public void set(T value) {
    2. Thread t = Thread.currentThread();
    3. ThreadLocalMap map = getMap(t);
    4. if (map != null) {
    5. map.set(this, value);
    6. } else {
    7. createMap(t, value);
    8. }
    9. }

            首先获取了当前的线程。每个线程都有一个容器(ThreadLocalMap)。map.set(this)就是将ThreadLocal作为key,因为我们的组件中需要传输的对象可能有多个。后面的createMap是初始化Map。

            set的源码如下:

    1. public T get() {
    2. Thread t = Thread.currentThread();
    3. ThreadLocalMap map = getMap(t);
    4. if (map != null) {
    5. ThreadLocalMap.Entry e = map.getEntry(this);
    6. if (e != null) {
    7. @SuppressWarnings("unchecked")
    8. T result = (T)e.value;
    9. return result;
    10. }
    11. }
    12. return setInitialValue();
    13. }

            其中this指的是ThreadLocal对象,通过它才知道是哪个ThreadLocalMap。entry.value是获取工具箱。

    Listener(监听器)

            Servlet规范中定义的一种特殊类,它用于监听Web应用程序中的ServletContext,HttpSession 和HttpServletRequest等域对象的创建与销毁事件,以及监听这些域对象中的属性发生修改的事件。

            部分示例:

            1,ServletContextListener-监听ServletContext对象的创建和销毁的过程

            2,HttpSessionListener-同理

            3,ServletRequestListener

            4,ServletContextAttributeListener-监听ServletContext的保存域的改动

            5,HttpSessionBindingListener-监听某个对象在session中的绑定与移除

            

  • 相关阅读:
    第十五章 插口层
    颜色扩散类dp及其优化:0919T2
    在腾讯云服务器OpenCLoudOS系统中安装maven(有图详解)
    【C#】依赖注入及Autofac
    springboot医疗管理系统毕业设计源码015221
    梳理Langchain-Chatchat知识库API接口
    关于 在Qt中的timerEvent信号中设置QCustomplot的日期时间轴范围乱蹿(编译器优化变量volatile) 的解决方法
    【学习笔记】ARC146/AGC020/
    酌情参考——chatGPT给的一些语义框架的学术思路,语义和图谱结合似乎是个不错的方向
    get_started_3dsctf_2016
  • 原文地址:https://blog.csdn.net/small_py_trade/article/details/127588891