首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

转载SPRING解决事宜

2014-01-15 
转载SPRING解决事务?分类:?Java2013-09-25 10:32?378人阅读?评论(0)?收藏?举报前文提到,最新换了框架,新项

转载SPRING解决事务
?

分类:?Java2013-09-25 10:32?378人阅读?评论(0)?收藏?举报

前文提到,最新换了框架,新项目用SpringMVC + Spring JdbcTemplate。搭框架时,发现了一个事务无法正常回滚的问题,记录如下:

首先展示问题:

Spring?applicationContext.xml配置:

?

[html]?view plaincopy?
  1. ?????????
  2. <bean?id="dataSource"?class="org.springframework.jndi.JndiObjectFactoryBean">??
  3. ????<property?name="jndiName">??
  4. ????????<value>java:comp/env/jdbc/will</value>??
  5. ????</property>??
  6. </bean>???
  7. ??????
  8. <bean?id="jdbcTemplate"?class="org.springframework.jdbc.core.JdbcTemplate">??
  9. ????<property?name="dataSource"?ref="dataSource"?/>??
  10. </bean>??
  11. ??
  12. <bean?id="txManager"??
  13. ????class="org.springframework.jdbc.datasource.DataSourceTransactionManager">??
  14. ????<property?name="dataSource"?ref="dataSource"?/>??
  15. </bean>??
  16. ??
  17. <!--?事务控制???-->??
  18. <tx:annotation-driven?transaction-manager="txManager"?/>??

?

Spring mvc.dispatcher.xml配置:

?

[html]?view plaincopy?
  1. <!--?自动扫描的包名?-->????
  2. <context:component-scan?base-package="com.will"?>???
  3. </context:component-scan>??
  4. ??
  5. <!--?默认的注解映射的支持?-->??
  6. <mvc:annotation-driven?/>??
  7. ??
  8. <!--?对静态资源文件的访问??-->????
  9. <mvc:default-servlet-handler/>????
  10. ????
  11. ??????
  12. <!--?拦截器????
  13. <mvc:interceptors>????
  14. ????<bean?class="com.will.mvc.MyInteceptor"?/>????
  15. </mvc:interceptors>???
  16. -->???
  17. ??
  18. <!--?视图解释类?-->???
  19. <bean?id="viewResolver"????
  20. ????class="org.springframework.web.servlet.view.UrlBasedViewResolver">????
  21. ????<property?name="viewClass"??value="org.springframework.web.servlet.view.JstlView"?/>????
  22. ????<property?name="prefix"?value="/WEB-INF/pages/"?/>????
  23. ????<property?name="suffix"?value=".jsp"?/>????
  24. </bean>?????

然后在Service层模拟了一个事务回滚的method case:

?

?

[java]?view plaincopy?
  1. @Transactional??
  2. public?boolean?save(Person?person)??
  3. {??
  4. ???for(int?id:?new?int[]{2,3})??
  5. ????{??
  6. ????????personDao.del(id);??
  7. ????????int?j?=?1/0;??
  8. ????}??????????????????
  9. ?????
  10. ????return?false;??
  11. }??

本以为大功告成,在运行save方法时,由于1/0 抛出?java.lang.ArithmeticException: / by zero??RuntimeException,导致事务回归。However,no way! So crazy~查了下,发现Spring MVC对于事务配置比较讲究,需要额外的配置。解决办法如下:

?

需要在?applicationContext.xml增加:

?

[html]?view plaincopy?
  1. <context:component-scan?base-package="com.will">???
  2. ????<context:exclude-filter?type="annotation"?expression="org.springframework.stereotype.Controller"?/>???
  3. </context:component-scan>??

在?Spring mvc.dispatcher.xml增加:

?

?

[html]?view plaincopy?
  1. <context:component-scan?base-package="com.will"?>???
  2. ????<context:include-filter?type="annotation"?expression="org.springframework.stereotype.Controller"?/>???
  3. ????<context:exclude-filter?type="annotation"?expression="org.springframework.stereotype.Service"?/>????
  4. </context:component-scan>??

?

由于web.xml中配置:

?

[html]?view plaincopy?
  1. <context-param>??
  2. ????<param-name>contextConfigLocation</param-name>??
  3. ????<param-value>??
  4. ?????????????classpath:applicationContext.xml??
  5. ????</param-value>??
  6. </context-param>??
  7. <listener>??
  8. ????<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>??
  9. </listener>??
  10. <servlet>??
  11. ????<servlet-name>dispatcher</servlet-name>??
  12. ????<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>??
  13. ????<init-param>??
  14. ?????????<param-name>contextConfigLocation</param-name>??
  15. ?????????<param-value>classpath*:/mvc_dispatcher_servlet.xml</param-value>??
  16. ????</init-param>??
  17. ????<load-on-startup>1</load-on-startup>??
  18. </servlet>??
  19. <servlet-mapping>??
  20. ????<servlet-name>dispatcher</servlet-name>??
  21. ????<url-pattern>*.do</url-pattern>??
  22. </servlet-mapping>??

?

?

Spring容器优先加载由ServletContextListener(对应applicationContext.xml)产生的父容器,而SpringMVC(对应mvc_dispatcher_servlet.xml)产生的是子容器。子容器Controller进行扫描装配时装配的@Service注解的实例是没有经过事务加强处理,即没有事务处理能力的Service,而父容器进行初始化的Service是保证事务的增强处理能力的。如果不在子容器中将Service exclude掉,此时得到的将是原样的无事务处理能力的Service。

?

经过以上分析,故可以优化上述配置

?

在?applicationContext.xml增加:

?

[html]?view plaincopy?
  1. <context:component-scan?base-package="com.will">???
  2. </context:component-scan>??

在?Spring mvc.dispatcher.xml增加:

?

?

[html]?view plaincopy?
  1. <context:component-scan?base-package="com.will"?>??????
  2. ????<context:exclude-filter?type="annotation"?expression="org.springframework.stereotype.Service"?/>????
  3. </context:component-scan>??
?

经过如上配置,可以发现事务控制部分的日志如下:

?

[html]?view plaincopy?
  1. 2013-09-25?09:53:13,031?[http-8080-2]?DEBUG?[org.springframework.transaction.annotation.AnnotationTransactionAttributeSource]?-?Adding?transactional?method?'save'?with?attribute:?PROPAGATION_REQUIRED,ISOLATION_DEFAULT;?''??
  2. 2013-09-25?09:53:13,037?[http-8080-2]?DEBUG?[org.springframework.beans.factory.support.DefaultListableBeanFactory]?-?Returning?cached?instance?of?singleton?bean?'txManager'??
  3. 2013-09-25?09:53:13,050?[http-8080-2]?DEBUG?[org.springframework.jdbc.datasource.DataSourceTransactionManager]?-?Creating?new?transaction?with?name?[com.will.service.impl.PersonServiceImpl.save]:?PROPAGATION_REQUIRED,ISOLATION_DEFAULT;?''??
  4. 2013-09-25?09:53:13,313?[http-8080-2]?DEBUG?[org.springframework.jdbc.datasource.DataSourceTransactionManager]?-?Acquired?Connection?[jdbc:mysql://localhost:3306/mvc?useUnicode=true&characterEncoding=UTF-8,?UserName=root@localhost,?MySQL-AB?JDBC?Driver]?for?JDBC?transaction??
  5. 2013-09-25?09:53:13,323?[http-8080-2]?DEBUG?[org.springframework.jdbc.datasource.DataSourceTransactionManager]?-?Switching?JDBC?Connection?[jdbc:mysql://localhost:3306/mvc?useUnicode=true&characterEncoding=UTF-8,?UserName=root@localhost,?MySQL-AB?JDBC?Driver]?to?manual?commit??
  6. 2013-09-25?09:53:13,327?[http-8080-2]?DEBUG?[org.springframework.jdbc.core.JdbcTemplate]?-?Executing?prepared?SQL?update??
  7. 2013-09-25?09:53:13,328?[http-8080-2]?DEBUG?[org.springframework.jdbc.core.JdbcTemplate]?-?Executing?prepared?SQL?statement?[delete?from?person?where?id=?]??
  8. 2013-09-25?09:53:13,348?[http-8080-2]?DEBUG?[org.springframework.jdbc.core.JdbcTemplate]?-?SQL?update?affected?1?rows??
  9. 2013-09-25?09:53:13,363?[http-8080-2]?DEBUG?[org.springframework.jdbc.datasource.DataSourceTransactionManager]?-?Initiating?transaction?rollback??
  10. 2013-09-25?09:53:13,364?[http-8080-2]?DEBUG?[org.springframework.jdbc.datasource.DataSourceTransactionManager]?-?Rolling?back?JDBC?transaction?on?Connection?[jdbc:mysql://localhost:3306/mvc?useUnicode=true&characterEncoding=UTF-8,?UserName=root@localhost,?MySQL-AB?JDBC?Driver]??
  11. 2013-09-25?09:53:13,377?[http-8080-2]?DEBUG?[org.springframework.jdbc.datasource.DataSourceTransactionManager]?-?Releasing?JDBC?Connection?[jdbc:mysql://localhost:3306/mvc?useUnicode=true&characterEncoding=UTF-8,?UserName=root@localhost,?MySQL-AB?JDBC?Driver]?after?transaction??
  12. 2013-09-25?09:53:13,378?[http-8080-2]?DEBUG?[org.springframework.jdbc.datasource.DataSourceUtils]?-?Returning?JDBC?Connection?to?DataSource??

在2013-09-25 09:53:13,363处进行了rollback。

热点排行