开始我打算在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"; } }