在项目中,@Transactional(rollbackFor=Exception.class),如果类加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。
在@Transactional注解中如果不配置rollbackFor属性,那么事物只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事物在遇到非运行时异常时也回滚
@Transactional(rollbackFor = Exception.class)
public void addHazardMater1(HazardMaterQO qo) {
HazardMater hazardMater = BeanCopyUtil.copyBeanClass(qo, HazardMater.class);
try{
hazardMaterMapper.insertSelective(hazardMater);
}catch (Exception e){
throw new BusinessException(RequestCodeEnum.MATER_IS_EXIST);
}
}
用try-catch 捕捉异之后可以throw一个新的异常,如,throw new RuntimeException(“事务回滚”);
但是这种情况下前端报错,很不友好,所以最好自己定义一个异常类
public class BusinessException extends RuntimeException {
private String code;
private String msg;
public BusinessException(RequestCodeEnum requestCodeEnum) {
this.code = requestCodeEnum.getCode();
this.msg = requestCodeEnum.getMsg();
}
public BusinessException(String code,String msg) {
this.code = code;
this.msg = msg;
}
public BusinessException(String msg) {
this.msg = msg;
}
public String getResponseCode() {
return code;
}
public void setResponseCode(String responseCode) {
this.code = responseCode;
}
@Override
public String getMessage() {
return msg;
}
public void setMessage(String message) {
this.msg = message;
}
}
其中的RequestCodeEnum 是个枚举类,用来存放错误数据的编码
public enum RequestCodeEnum {
OK("00","成功"),
ERROR("20","服务器错误"),
PARAM_ERROR("30","请求参数错误"),
MATER_IS_EXIST("40", "该数据已重复")
;
private String code;
private String msg;
private RequestCodeEnum(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
或者设置手动回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackonly();
@Transactional(rollbackFor = Exception.class)
public void addHazardMater1(HazardMaterQO qo) {
HazardMater hazardMater = BeanCopyUtil.copyBeanClass(qo, HazardMater.class);
try{
hazardMaterMapper.insertSelective(hazardMater);
}catch (Exception e){
TransactionAspectSupport.currentTransactionStatus().setRollbackonly();
}
}
2、数据库引擎不支持事务
这里以 MySQL 为例,其 MyISAM 引擎是不支持事务操作的,InnoDB 才是支持事务的引擎,一般要支持事务都会使用 InnoDB。
3、方法不是public以下来自 Spring 官方文档:
When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.4、自身调用问题: 默认只有在外部调用时候才生效,自身调用没有用
在类内部没有添加@Transactional的方法,调用了@Transactional方法时,当你调用时,他也不会回滚
@Service
public class Testservice{
public void add(QO qo) {
addQo(qo);
}
@Transactional
public void addQo(QO qo) {
// add Qo
}
}
失败的原理:@Transactional是基于动态代理对象来实现的,而在类内部的方法的调用是通过this关键字来实现的,没有经过动态代理对象,所以事务回滚失效。
5、没有被Spring管理:service注解被注掉了//@Service
public class Testservice{
@Transactional
public void addQo(QO qo) {
// add Qo
}
}



