昨天发了一篇关于事务不回滚的文章。问题就是注解扫描的问题。今天就想写一篇事务处理的详细文章。
说到spring的事务处理,不得不先说一下ssm框架主要的两个配置文件 一个是spring的,一个是springmvc的(其实还有一个mybaties的配置文件,但基本和spring的写在一起了)
springmvc的配置文件
<!-- 扫描control包 -->
<context:component-scan base-package="com.dncps.action" />
<!-- 配置映射器与适配器 -->
<mvc:annotation-driven></mvc:annotation-driven>
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/fonts/**" location="/fonts/"/>
<mvc:resources mapping="/images/**" location="/images/"/>
spring配置文件
<!-- 1扫描所有包的文件 -->
<context:component-scan base-package="com.dncps.*" />
<!-- 2加载数据资源文件 -->
<context:property-placeholder location="classpath:resources/db.properties" />
<context:property-placeholder location="classpath:resources/log4j.properties" />
<!-- 3配置数据源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- 自动转json,处理乱码 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="mappingJackson2HttpMessageConverter" />
</list>
</property>
</bean>
<bean id="mappingJackson2HttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>text/json;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
<!-- 4配置sessionfactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->
<property name="typeAliasesPackage" value="com.dncps.value" />
<!-- 显式指定Mapper文件位置 -->
<property name="mapperLocations" value="classpath:mapper/*Mapper.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 5配置session -->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory" />
</bean>
<!-- 6、声明式事务管理,依赖于前面声明的dataSource数据源 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 7、注解事务切面 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 8总错误处理-->
<bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="defaultErrorView">
<value>/error/error</value>
</property>
<property name="defaultStatusCode">
<value>500</value>
</property>
<property name="warnLogCategory">
<value>org.springframework.web.servlet.handler.SimpleMappingExceptionResolver</value>
</property>
</bean>
service层的,在service层控制事务进行回滚要使用@Transactional
注释的方式其中rollbackfor参数是遇到什么异常触发回滚,Throwable.class就是所有异常,当然仅限这个方法。如果想应用于 整个类,可以把注释在类上面。
在下面的代码中有一个错误int yichagn=1/0;
当遇到异常后因为没有执行carddao.updateuserfromcarddao(user);方法,所以carddao.updatecard(map2);
这个方法会回滚
数据库数据不改变。
@Transactional(rollbackFor = Throwable.class)
@Override
public void recharge1(HttpSession session, HttpServletRequest request,
HttpServletResponse response) throws Exception {
Map<String, String> map = new HashMap<String, String>();
Map<Object,Object> map2 = new HashMap<Object,Object>();
String cardid=request.getParameter("cardid");
String cardnumber=request.getParameter("cardnumber");
String code=request.getParameter("code");
if("".equals(cardid)||"".equals(cardnumber)||"".equals(code)){
response.getWriter().write("账号、密码、验证码不能为空!");
}else if(code.equals(session.getAttribute("cardsafecode"))){
map.put("cardid", cardid);
map.put("cardnumber", cardnumber);
card getcardByidandnumber = carddao.getcardByidandnumber(map);
if(getcardByidandnumber !=null){
if(getcardByidandnumber.getCardstate()==0){
response.getWriter().write("对不起,充值失败,此卡尚未出库!");
}else if(getcardByidandnumber.getCardstate()==1){
user attribute = (user) session.getAttribute("user");
user user=new user();
map2.put("cardstate",2);
map2.put("cardid", cardid);
Format f = new SimpleDateFormat("yyyy-MM-dd");
Calendar c = Calendar.getInstance();
c.add(Calendar.MONTH, 6);
user.setUserpaytime(f.format(c.getTime()));
user.setUserid(Integer.valueOf(attribute.getUserid()));
user.setUsertype(1);
carddao.updatecard(map2);
int yichagn=1/0;//异常
carddao.updateuserfromcarddao(user);
response.getWriter().write("true");
}else if(getcardByidandnumber.getCardstate()==2){
response.getWriter().write("充值失败,此卡已经被人充值,若有疑问请联系!!");
}
}else{
response.getWriter().write("无此卡!");
}
}else{
response.getWriter().write("验证码错误!");
}
}
最后说一下,因为自带的事务处理机制所以要在spring中进行包扫描,而不能认为springmvc中进行扫描过后就不用在spring配置文件中扫描了。