开始我打算在controller里面控制回滚,但尝试很多次无效,于是还是老实的在service里面控制事物回滚。
mysql需要表类型类为innoDB才行。有人说用mysql的话要关闭自动提交autocommit才行,我亲测不关也没问题。
不上不管开不开都可以正常回滚。
关于配置,注意点是spring-mvc中扫描注入时不要扫描service。原因是spring mvc扫描出来的service是不带事物功能的,它主要是负责扫描controller的。spring扫描出来的service才具备事物功能。
spring-mvc.xml: (不要扫描service)
<!-- 添加注解驱动 -->
<mvc:annotation-driven />
<mvc:resources mapping="/**" location="/" />
<!-- 扫描controller(controller层注入) -->
<context:component-scan base-package="com.zhuhuixin">
<!--不扫描service层-->
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Service" />
</context:component-scan>
spring-mybatis.xml: (随意扫描,controller,service都扫描也行)
<!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
<!-- 扫描controller(service层注入) -->
<context:component-scan base-package="com.zhuhuixin">
</context:component-scan>
配置完成后我们来看controller和service
// 保存角色
@ResponseBody
@RequestMapping(value = "saveRole", produces = "text/plain;charset=UTF-8")
public String saveRole(@RequestParam Map<String,String> params, HttpServletRequest req) {
roleService.saveRole(params,req);
return "success";
}
service:
service中注意要在方法或者类前面加@Transactional才行,不然回滚不生效。我建议直接加在类前面,不需要每个方法前都加一次。service中可以不用try catch捕获异常,如果非要捕获异常,一定要抛出runtimeException才能正常回滚。
@Service
@Transactional
public class RoleService {
@Resource
private RoleMapper roleMapper;
public String saveRole(Map<String,String> params, HttpServletRequest req) {
Integer roleId = Integer.parseInt(req.getParameter("roleId"));
String[] funcIds = req.getParameterValues("funcId");
TSystemRole rolePO = new TSystemRole();
try {
if(roleId!=null){
rolePO=roleMapper.findRoleById(roleId);
rolePO.setModifyDate(new Date());
}else{
rolePO.setCreateDate(new Date());
}
rolePO.setRoleParent(Integer.parseInt(params.get("roleParent")));
rolePO.setRoleCode(params.get("roleCode"));
rolePO.setRoleName(params.get("roleName"));
rolePO.setRoleStatus(params.get("roleStatus"));
rolePO.setRoleDescription(params.get("roleDescription"));
if(roleId!=null){
//清除角色所有菜单
roleMapper.removeRoleFuncs(roleId);
roleMapper.updateRole(rolePO);
}else{
roleMapper.insertRole(rolePO);
}
if(funcIds!=null){
for(int i=0;i<funcIds.length;i++){
roleMapper.addRoleFunc(rolePO.getRoleId(),Integer.parseInt(funcIds[i]));
}
}
}catch (Exception e){
//e.printStackTrace();
throw new RuntimeException();
}
return "success";
}
}