在实际开发场景中,有时候为了减少代码的冗余,在编写数据执行方法时,希望一个方法同时执行两个sql脚本,顺序执行,不影响业务逻辑。
1、在数据源配置中增加如下配置:allowMultiQueries=true
spring:
profiles: dev
datasource:
#主数据源
master:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&useSSL=false&serverTimezone=UTC&allowMultiQueries=true
username: root
password: 123456
2、多sql语句以分号;相隔
<update id="updateId" parameterType="java.lang.Integer">
update t_menu set name = #{name} where id = #{id};
update t_stu set order_no = order_no+1 where id = #{id};
</update>
注意:多条sql语句同时执行,不存在事务,即其中一条sql语句报错不会影响另外一条语句执行。
解决办法:在service层方法里添加@Transactional注解,添加@Transactional注解后,spring默认抛出未检查unchecked异常(继承自RuntimeException的异常)或者Error才会回滚,换句话说,若只是添加@Transactional注解,对于RuntimeException异常或者Error错误默认会触发事务回滚,对于其他的异常是不会触发异常的,若此时想要其他异常也能触发回滚,需要添加@Transactional的rollbackFor属性值,比如在代码中手动抛出Exception异常,如下:
if (res > 0) {
// 抛出异常,事物捕抓异常,事物进行回滚
throw new Exception("无权限审批!");
}
此时加上rollbackFor属性值如下,当出现Exception异常时,可以触发事务回滚。
@Transactional(rollbackFor = Exception.class)
建议:自定义一个异常处理类,该异常类继承RuntimeException类,在需要抛出异常时,调用该自定义异常类,此时方法执行出现异常,会抛出RuntimeException,在方法头加上@Transactional即可,而不需要添加rollbackFor属性值。