手动回滚
Object savePoint =null;//回滚点 try{ savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();//设置回滚点 int res=fbusiMapper.updatePharmAudit(param); if(res>0){ res=fbusiMapper.addPresAudit(param); } if(res<=0){//防止添加成功,修改失败 if(savePoint!=null){ TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint); } } return res; }catch (Exception e){ e.printStackTrace(); logger.error("删除f_user_info表数据"+ Log4jUtils.getTrace(e)); if(savePoint!=null){//防止异常 TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint); } throw new FPSMException("删除f_user_info表数据"+ Log4jUtils.getTrace(e)); }
声明式的事务
<!-- DataSource --> <bean name="fbusiDataSource" init-method="init" destroy-method="close" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${mySqlDriverClassName}"/> <property name="url" value="${spring.datasource.fbusi.url}" /> <property name="username" value="${spring.datasource.fbusi.username}" /> <property name="password" value="${spring.datasource.fbusi.password}" /> <!-- 初始化连接大小 --> <property name="initialSize" value="10" /> <!-- 连接池最大使用连接数量 --> <property name="maxActive" value="100" /> <!-- 连接池最小空闲 --> <property name="minIdle" value="10" /> <!-- 获取连接最大等待时间 --> <property name="maxWait" value="60000" /> <!-- <property name="poolPreparedStatements" value="true" /> <property name="maxPoolPreparedStatementPerConnectionSize" value="33" /> --> <property name="validationQuery" value="SELECT 1" /> <property name="testOnBorrow" value="false" /> <property name="testOnReturn" value="false" /> <property name="testWhileIdle" value="true" /> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="25200000" /> <!-- 打开removeAbandoned功能 --> <property name="removeAbandoned" value="true" /> <!-- 1800秒,也就是30分钟 --> <property name="removeAbandonedTimeout" value="1800" /> <!-- 关闭abanded连接时输出错误日志 --> <property name="logAbandoned" value="true" /> <!-- 监控数据库 --> <!-- <property name="filters" value="mergeStat" /> --> <property name="filters" value="stat" /> </bean>
<!-- SqlSessionFactory --> <bean id="fbusiSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="fbusiDataSource" /> <!-- 自动扫描mapping.xml文件 --> <property name="mapperLocations" value="classpath*:com/wc/fpsm/fbusi/mapper/*.xml"></property> <property name="plugins"> <array> <bean class="com.github.pagehelper.PageInterceptor"> <property name="properties"> <value> <!-- 该参数默认为false --> <!-- 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 --> <!-- 和startPage中的pageNum效果一样--> offsetAsPageNum=true <!-- 该参数默认为false --> <!-- 设置为true时,使用RowBounds分页会进行count查询 --> rowBoundsWithCount=true <!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 --> <!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型)--> pageSizeZero=true <!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 --> <!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 --> <!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 --> reasonable=true <!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法 --> <!-- 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 --> <!-- 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值 --> <!-- 不理解该含义的前提下,不要随便复制该配置 --> params=pageNum=start;pageSize=limit; </value> </property> </bean> </array> </property> </bean>
<!-- DAO接口所在包名,Spring会自动查找其下的类 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.wc.fpsm.fbusi.dao" /> <property name="sqlSessionFactoryBeanName" value="fbusiSqlSessionFactory"></property> </bean>
<!-- 事务管理 --> <bean id="fbusiTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="fbusiDataSource" /> </bean>
<!-- 注解方式配置事物 --> <tx:annotation-driven transaction-manager="fbusiTransactionManager" />
<!--fbusiDB 拦截器方式配置事物 --> <tx:advice id="fbusiDBtransactionAdvice" transaction-manager="fbusiTransactionManager"> <tx:attributes> <tx:method name="add*" propagation="REQUIRED" /> <tx:method name="append*" propagation="REQUIRED" /> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="modify*" propagation="REQUIRED" /> <tx:method name="edit*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="remove*" propagation="REQUIRED" /> <tx:method name="init" propagation="REQUIRED" /> <tx:method name="delAndInit" propagation="REQUIRED" /> <tx:method name="get*" propagation="REQUIRED" /> <tx:method name="find*" propagation="REQUIRED" read-only="true" /> <tx:method name="load*" propagation="REQUIRED" read-only="true" /> <tx:method name="search*" propagation="REQUIRED" read-only="true" /> <tx:method name="datagrid*" propagation="REQUIRED" read-only="true" /> <tx:method name="*" propagation="REQUIRED" read-only="false"/> </tx:attributes> </tx:advice>
<!-- aop切入点 --> <aop:config> <aop:pointcut id="fbusiDBtransactionPointcut" expression="execution(* com.wc.fpsm.fbusi.impl.*Impl.*(..))" /> <!-- <aop:pointcut id="transactionPointcut" expression="execution(public * *(..))" /> --> <aop:advisor pointcut-ref="fbusiDBtransactionPointcut" advice-ref="fbusiDBtransactionAdvice" /> </aop:config>
/* ServiceImpl */ @Override @Transactional(propagation = Propagation.REQUIRED,rollbackFor=FPSMException.class) public Integer addPharmAudit(BusiVO param) throws FPSMException { int res=fbusiMapper.updatePharmAudit(param); if(res>0){ res=fbusiMapper.addPresAudit(param); } return res; }
注:有try/catch,必须抛出异常
1、如果catch中throw Exception,并且rollbackFor=Exception.class,则能够成功回滚。
2、自定义的FPSMException异常需要继承RuntimeException,否则会失效,例:如果FPSMException继承Exception,则下例回滚失效。
3、声明式异常只有出现运行时异常并且不被捕获才会回滚,在编程式事务中出现异常要显式的调用rollback进行回滚。
例:
@Override @Transactional(propagation = Propagation.REQUIRED,rollbackFor=FPSMException.class) public Integer addPharmAudit(BusiVO param) throws FPSMException { try{ int res=fbusiMapper.updatePharmAudit(param); if(res>0){ res=fbusiMapper.addPresAudit(param); } return res; }catch (Exception e){ e.printStackTrace(); throw new FPSMException("addPharmAudit:"+ Log4jUtils.getTrace(e)); } }