一、SSH整合之后事务问题和总结

  1.引入问题:DAO层测试

    假设将User对象设置为懒加载模式,在dao层使用load方法。

    

    注意,注释不要放开。

    使用如下的代码块进行测试:

    会报错:no session。

    

    为什么会没有session呢,因为在代码

User user=(User) hibernateTemplate.load(User.class, id);

    执行完成之后session就已经关闭了。

  2.Service层测试

    (1)Service层代码:

    

      DAO层代码:

     

      测试代码:

    

    运行结果:

    

    出现的错误结果和上面完全相同。

    (2)解决错误

      将DAO层中的代码注释去掉或者将Service中的代码注释去掉。

      注释的代码作用是打印结果,只是一个System.out.println方法的执行;虽然如此,程序运行不再有问题。

      

  3.原因分析

    (1)为什么测试DAO无论怎么测试都会报出异常?

       因为DAO层调用完成getUserById方法之后session就马上关闭了,所以执行下一句代码的时候即使是打印输出的代码也会报错。

    (2)为什么测试Service的时候如果没有去掉注释的话,就会出错?

       因为去掉注释的话,Service层调用完成getUserById方法之后Session就会关闭,效果和在DAO层是完全相同的,所以结果和在DAO层是完全相同的。报错的信息完全相同。

    (3)为什么Service层去掉注释之后就不报错了?

      Service层去掉注释之后由于方法还没有退出,所以会将数据保存到User对象中;所以数据已经保存到了内存中,这样就不会报错了。

    (4)在DAO层去掉注释之后会不会报错?

      去掉DAO层的注释之后的运行结果:

      

      结果是没有报错,为什么,DAO层调用完成查询的方法之后不是会立即关闭session吗?

        结果是没有关闭Session,原因是在Service层调用的方法,该方法具有事务,而且该事务的范围扩展到了DAO层。最根本的原因是在Spring配置文件中的配置:

      

      propagation属性值是默认的,所以在Service层中方法执行的时候,执行的所有方法都将会带有事务,直到方法结束,事务也会随之结束,因此DAO层才没有立即结束事务(关闭session)。

  4.总结SSH整合之后事务管理的范围

    (1)如果当前执行的方法没有事务环境,当执行完成this.hibernateTemplate中的方法之后session立即关闭。

    (2)如果当前执行的方法有事务环境,当事务环境的方法被调用完成之后session关闭。

  5.通过以上的分析和总结可以得到如果直接在Action中调用Service层中的方法,如果出现异常,肯定不能回滚,例如下面中的测试代码:   

    

    很明显,这里有/0的异常,所以如果事务能够回滚,则不会发出insert的sql语句。但是结果却是:

    

    所以事务回滚失败了。原因就是Service对象中的每一个方法执行完成之后都会立即关闭session,事务也随之消失。相同Service中的方法调用多次或者相同Service中的不同方法执行的时候一定不会在同一个事务中。

二、解决SSH整合之后的事务问题

  解决方法就是使用OSIV模式(Open Session In View),即在MVC中的View层就开启事务,这样就扩展了事务的范围。

  只是在web.xml文件中加上如下的配置即可:

    <!-- 使用OSIV模式解决事务回滚问题,只需要添加一个监听器就可以了 -->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>

  也就是说只是增加了一个过滤器而已,应当注意该过滤器放置的位置应当在下面的配置上面:

<filter>
<filter-name>strutsFilter</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>strutsFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>

  否则添加的过滤器不生效。完整的web.xml文件配置如下:

 <?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <!-- 使用OSIV模式解决事务回滚问题,只需要添加一个监听器就可以了 -->
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping> <filter>
<filter-name>strutsFilter</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>strutsFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping> <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml</param-value>
</context-param> <welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

web.xml

  最后,使用OSIV模式应当注意的事项:

    1.使用OSIV模式之后,sessio的打开被提前了,session的关闭被延后了,这样就解决了懒加载引起的异常的问题。

    2.两个过滤器,OSIV的过滤器必须在struts2之前。

  使用OSIV模式的缺点:

    因为Session的关闭被延迟了,所以hibernate的一级缓存在session中,所以会导致大量的缓存数据长期保存在了内存中。

三、Struts2流程回顾

  1.启动服务器的时候干了两件事情。

    

      * dispatcher = init.initDispatcher(config);该句代码加载了各种各样的配置文件。

      * init.initStaticContentLoader(config, dispatcher); 该句代码完成了静态注入。

  2.当过滤器拦截到一个请求的时候做了什么事情

    查看doFilter方法中的源代码。

    (1)创建AciontContext对象。

      创建ActionContext对象的同时会同时创建ValueStack对象,而且创建ValueStack对象在前,创建ActionContext对象在后。

    两个对象同时创建,而且两个对象维护同一个Map对象,原因是创建ActionContext的时候使用的参数是ValueStack对象的context成员变量。

   通过代码ActionContext.setContext(tx);即可以将ActionContext放置到ThreadLocal中了,这样数据就安全了,下面是代码追踪。

    (2)创建ActionProxy对象

    init方法中执行了创建了对应的Action和所有的拦截器。

    

    最后在invocation的invoke方法中执行所有的拦截器、执行当前请求的action、执行结果集。

    

四、Struts2的完整流程图

  

最后附上项目源代码:https://github.com/kdyzm/day53_ssh_oa

【Java EE 学习 54】【OA项目第一天】【SSH事务管理不能回滚问题解决】【struts2流程回顾】的更多相关文章

  1. Java EE 学习(8):IDEA + maven + spring 搭建 web(4)- 用户管理

    转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) ava E ...

  2. Java EE 学习(9):IDEA + maven + spring 搭建 web(5)- 博客文章管理

    转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) . 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) Jav ...

  3. Java EE 学习(7):IDEA + maven + spring 搭建 web(3)- 配置数据库

    参考: https://my.oschina.net/gaussik/blog/513444 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 ...

  4. Java EE 学习(6):IDEA + maven + spring 搭建 web(2)- 配置 Spring

    参考:https://my.oschina.net/gaussik/blog/513353 注:此文承接上一文:Java EE 学习(5):IDEA + maven + spring 搭建 web(1 ...

  5. Java EE 学习(5):IDEA + maven + spring 搭建 web(1)

    参考:http://www.cnblogs.com/lonelyxmas/p/5397422.html http://www.ctolib.com/docs-IntelliJ-IDEA-c--1590 ...

  6. Java EE 学习(4):IDEA + maven 搭建 web(2)

    参考:http://www.bubuko.com/infodetail-1855067.html 现使用 Maven 创建项目:本节接Java EE 学习(3):IDEA + maven 搭建 web ...

  7. Java EE学习——Quartz的Cron表达式

    经历过低谷后,还是要好好学习,越失落会越来越落后. 今天写一下Cron表达式的用法,虽然是之前自己写的,也过了挺长一段时间,这次就拿出来作为回顾吧. Cron表达式是Quartz的精髓(个人觉得),比 ...

  8. Spring 4 官方文档学习(九)数据访问之事务管理

    说明:未整理版,未完待续,请绕行 本部分的重点是数据访问以及数据访问层与业务层之间的交互. 1.Spring框架的事务管理 介绍 http://docs.spring.io/spring/docs/c ...

  9. SSM保姆级从创建项目到使用,包括事务和设置回滚

    1. 简介 Spring 和 Mybaits整合 2. 创建项目 负责将代理类记性扫描,扫描的是Mapper接口所在的包,这个是mybatis提供的,所以会去找SqlSessionFactory 2. ...

随机推荐

  1. 【原】小搞一下 javascript算法

    前言:在前端大全中看到这句话,以此共勉.基础决定你可能达到的高度, 而业务决定了你的最低瓶颈 其实javascript算法在平时的编码中用处不大,不过不妨碍我们学习它,学习一下这些算法的思想,锻炼一下 ...

  2. IDF-CTF-牛刀小试-啥?

    本人属于Web安全这一块的小白,稍微了作了一下知识补充就开始了CTF,其中的有很多不懂但看多了网上大牛的解题办法和思路.便开始有了一些要想动手记录的冲动,希望大家共同进步学习,本文能对读者有所帮助~ ...

  3. 12月15日smarty模板基本语法

    smarty基本语法: 1.注释:<{* this is a comment *}>,注意左右分隔符的写法,要和自己定义的一致. <{* I am a Smarty comment, ...

  4. linux系统运维常用基本命令详解

      1.ls 文件属性:  -:普通文件  d:目录文件  b:块设备  c:字符设备文件  l:符号连接文件  p:命令管道  s:套接字文件  文件权限: 9位数字,每3位一组  文件硬链接次数  ...

  5. ss命令和Recv-Q和Send-Q状态

    ss 用来显示处于活动状态的套接字信息.ss命令可以用来获取socket统计信息,它可以显示和netstat类似的内容.但ss的优势在于它能够显示更多更详细的有关TCP和连接状态的信息,而且比nets ...

  6. adobe premiere pro cc2015.0已停止工作 解决办法

    adobe premiere pro cc2015.0已停止工作 一直报错 解决办法就是: 删除我的电脑  我的饿文档下的 Adobe下的Premiere Pro文件夹 现象就是怎么重新安装都不管用P ...

  7. GCD总结

    //用block只有两种:同步执行/异步执行(参数1:队列;参数二:任务) dispatch_async(dispatch_get_global_queue(0, 0),^{ });//异步在新的线程 ...

  8. Java 静态内部类与非静态内部类 学习记录.

    目的 为什么会有这篇文章呢,是因为我在学习各种框架的时候发现很多框架都用到了这些内部类的小技巧,虽然我平时写代码的时候基本不用,但是看别人代码的话至少要了解基本知识吧,另外到底内部类应该应用在哪些场合 ...

  9. Apache服务器安装过程及问题的解决(for windows system32bit)

    在使用Hbuilder设计网站时,在制作本站搜索时,用到了Php文件,而Hbuilder的内置web服务器不支持php的解析, 所以需要安装配置外部服务器,有多个选择,我安装的apache服务器,并遇 ...

  10. Hibernate简易原生DAO的实现

    写在最前: 初学Hibernate,在尝试把JDBC项目移植到Hibernate的过程中,碰到了不少的麻烦,最让人心烦意乱的自然是SQL语句改动造成的代码混乱.其实不难,网上的解决方案有很多, 不过. ...