最近开发项目遇到spring事务回滚不了的问题,经过公司大师的指点终于可以了,现在跟大家 分享一下:
首先需要在web.xml配置如下信息,整个项目的入口都在这里:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>Vlike</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 我把数据库的配置和spring的其他配置分开写 jdbc-context.xml-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:jdbc-context.xml</param-value>
</context-param>
<!-- log4j配置,文件路径,因为是跟随项目启动 -->
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>classpath:log4j.properties</param-value>
</context-param>
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>ForceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--加载spring的主要配置 springMvc3-servlet.xml-->
<servlet>
<servlet-name>springMvc3</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springMvc3-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<session-config>
<session-timeout>120</session-timeout>
</session-config>
<servlet-mapping>
<servlet-name>springMvc3</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<error-page>
<error-code>404</error-code>
<location>/Vlike/page404.html</location>
</error-page>
<error-page>
<exception-type>java.lang.NullPointerException</exception-type>
<location>/Vlike/WEB-INF/jsp/error.jsp</location>
</error-page>
</web-app>
关于数据库事务的spring的配置jdbc-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd" default-autowire="byName">
<!-- 启用注解 -->
<context:annotation-config />
<!-- 启动组件扫描,排除@Controller组件,该组件由SpringMVC配置文件扫描 -->
<context:component-scan base-package="com">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<!-- 创建数据源 commons-dbcp.jar; commons-pool.jar包-->
<context:property-placeholder location="classpath:database.properties"/>
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean id="simpleJdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
<constructor-arg><ref bean="dataSource"/></constructor-arg>
</bean>
<!-- 看了spring源码,该 org.springframework.jdbc.core.JdbcTemplate类的继承类有dataSource属性,所以可以属性注入-->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
</bean>
<!--声明DataSourceTransaction事务-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 声明式事务管理 注意<tx:method name的写法,具体管理在sevice层@Transactional下面的方法-->
<tx:advice id="myAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" read-only="false" isolation="READ_COMMITTED"
rollback-for="java.lang.Exception"/>
<tx:method name="update*" propagation="REQUIRED" read-only="false" isolation="READ_COMMITTED"
rollback-for="java.lang.Exception"/>
<tx:method name="save*" propagation="REQUIRED" read-only="false" isolation="READ_COMMITTED"
rollback-for="java.lang.Exception" />
<tx:method name="del*" propagation="REQUIRED" read-only="false" isolation="READ_COMMITTED"
rollback-for="java.lang.Exception"/>
<tx:method name="*" propagation="REQUIRED" read-only="false" isolation="READ_COMMITTED"
rollback-for="java.lang.Exception"/>
<tx:method name="find*" read-only="false" isolation="READ_COMMITTED"/>
<tx:method name="get*" read-only="false" isolation="READ_COMMITTED"/>
</tx:attributes>
</tx:advice>
<!--aop定义具体事务扫描的是那些包-->
<aop:config>
<aop:advisor pointcut="execution(* com.imcore.*.service.impl.*Impl.*(..))" advice-ref="myAdvice"/>
</aop:config>
</beans>
spring的其他配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<!-- 启动项目时扫描所有的注解 -->
<context:component-scan base-package="com.imcore.*.action"/>
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>apolication/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<!-- 这里拦截器还有一种配置方法【针对路径进行配置】 推荐使用这个,方便直观-->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/system/*/*"/>
<mvc:mapping path="/system/*"/>
<mvc:mapping path="/system/"/>
<mvc:mapping path="/system"/>
<bean class="com.imcore.base.interceptor.SysAdminInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
<!-- 配置js,css等静态文件直接映射到对应的文件夹,不被DispatcherServlet处理 -->
<mvc:resources location="/WEB-INF/resources/**" mapping="/resources"/>
<mvc:resources mapping="/javascript/**" location="/static_resources/javascript/"/>
<mvc:resources mapping="/styles/**" location="/static/css/"/>
<mvc:resources mapping="/images/**" location="/static/images/"/>
<!-- 配置页面访问地址www.xxx.com/about返回的静态html文件 -->
<mvc:resources mapping="/about/**" location="/WEB-INF/html/"/>
<!-- 走servlet的默认配置,先走默认的web.xml配置的servlet,没有的话才找对应controller -->
<mvc:default-servlet-handler />
<!-- jsp页面解析器,当Controller返回XXX字符串时,先通过拦截器,然后该类就会在jsp/目录下,查找XXX.jsp文件-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!--对上传的图片进行上传大小的限制-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding">
<value>UTF-8</value>
</property>
<property name="maxUploadSize">
<value>32505856</value><!-- 上传文件大小限制约为31M,略大于1024*1024*31 -->
</property>
<property name="maxInMemorySize">
<value>4096</value>
</property>
</bean>
</beans>
接下来就开始在service层开始测试事务会不会回滚了,我们需要在service层的方法中写如下代码,然后遇到异常应该手动写RuntimeException异常抛出,然后如果你不想再前端看到500的错误,在你调用该service层的方法的时候controller层中需要进行try catch处理,不能再service层中进行try catch处理,亲测使用try catch块包住之后,当第二条sql发生异常,并不会回滚
@Transactional
public boolean updateNewUserName(String newUserName, String userName) {
boolean userFlag = false;
boolean soundFlag = false;
userFlag = userDao.updateNewUserName(newUserName, userName);
soundFlag = soundDao.updateNewUserName(newUserName, userName);
if (!userFlag || !soundFlag) {
logger.error("数据库更新异常,回滚数据");
//spring容器当遇到RuntimeException的时候才会进行回滚,所以需要我们手动的抛出,当时由于我没有手动抛出下面的异常,所以数据一直没有回滚
throw new RuntimeException("数据库更新异常,回滚数据");
}
return soundFlag && userFlag;
}
分享完毕!谢谢大家,有不足的地方欢迎大家交流,大家共同进步。