欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

@Transactional注解回滚(事物)

程序员文章站 2022-07-04 22:09:45
...

1 创建一个实体类,该类拥有的属性与数据库拥有的字段一一对应

import lombok.Data;
@Data
public class InterfaceTest {
private Integer interfaceId;
private String interfaceName;
private String interfaceType;
private String interfaceMethod;
private String interfaceAliasName;

}

2 数据库表拥有的字段@Transactional注解回滚(事物)
创建一个接口:写增删改查方法的接口,写入新增方法

import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface MyInterfaceTestMapper {
void addInterfaceTest(InterfaceTest interfaceTest);
}

创建一个xml文件:写增删改查sql的文件,写入新增sql

<mapper namespace="com.longteng.lesson2.my.mybatis.MyInterfaceTestMapper">
    <!--id就是接口中的方法名-->
    <insert id="addInterfaceTest"
            useGeneratedKeys="true"
            keyColumn="interface_test_id"
            keyProperty="interfaceId"
            parameterType="com.longteng.lesson2.my.mybatis.InterfaceTest">
            <!--给哪个表插入数据,就写哪个表-->
            insert into interface_test
            <!--给哪些字段插入数据,就写哪些字段名-->
            (interface_name,interface_method,interface_type,interface_alias_name)
            <!--要插入的数据是对应的哪些字段,就是实体类里的字段,要与字段名的先后顺序一一对应,用#{}接收-->
            values (#{interfaceName},#{interfaceMethod},#{interfaceType},#{interfaceAliasName})
    </insert>

事物:通过@Transactional进行事物回滚

多个操作放在一起执行叫事物
例如一个下订单的业务
最先执行的是插入数据库,但是插入数据库成功后,后续业务并没有成功,下订单业务还没有完全操作完毕,这个时候其实下订单已经失败了,那么插入数据的那条数据就是脏数据了,要做的就是对于事物没有成功的数据做回滚操作
事物分为编程事物管理、声明事物管理,例子中实现的是声明事物
编程事物:自己控制回滚流程,多用于复杂系统
声明事物:@Transactional注解控制回滚流程,多用于简单流程

import com.longteng.lesson2.my.mybatis.InterfaceTest;
import com.longteng.lesson2.my.mybatis.MyInterfaceTestMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class InterfaceService {
//注入接口
@Autowired
MyInterfaceTestMapper myInterfaceTestMapper;
//出现异常回滚,一般不指定的情况下出现rollback、error的异常才会回滚,出现Exception异常是不会回滚的,这里就是指定一下出现Exception也要做回滚
@Transactional(rollbackFor = Exception.class)
//返回Object类型的带参方法,抛出一个异常
public Object test(Integer i) throws Exception{
    //创建实体类的实例,通过实例向数据库中添加数据
    InterfaceTest interfaceTest=new InterfaceTest();
    interfaceTest.setInterfaceName("qwer");
    interfaceTest.setInterfaceMethod("GET");
    interfaceTest.setInterfaceType("HTTP");
    interfaceTest.setInterfaceAliasName("QWER");
    //接口类实例调用接口的新增方法,添加数据到数据库
    int i=myInterfaceTestMapper.addInterfaceTest(interfaceTest);
    //如果方法传参i不等于1就抛出异常,若等于1就正常返回,添加成功
    if(i!=1){
        throw new Exception();
    }else {
        return "添加成功";
    }
}
}

controller中

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class MyInterfaceController {
//注入回滚的业务类
@Autowired
InterfaceService interfaceService;
@RequestMapping("/interfaceService")
public @ResponseBody Object test(Integer i)throws Exception{
    return interfaceService.test(i);
}
}

浏览器请求 http://127.0.0.1:8080/interfaceService?i=1 i=1 添加数据到数据库成功

@Transactional注解回滚(事物)
浏览器请求 http://127.0.0.1:8080/interfaceService?i=2 i=2 添加数据到数据库失败

如果不用@Transactional,就算请求时i不等于1插入数据库也能成功
例子中,调用addInterfaceTest方法其实就是插入数据库操作,并且debug的话,sql的确是打印了,但是这个时候并没有插入数据库,因为用了回滚的注解,整个事物是一次提交,不是代码读到哪里就执行哪里,是等test方法整个执行完毕,才确定该sql要不要插入数据库

1 一般情况下一个方法(service层关于操作数据库的方法)就是一个事物
2 Spring事物的底层实现是靠AOP实现的
3 事物也是可以加在抽象类或者接口类上的,继承抽象类、实现接口类的那些子类也就继承到了事物这个类