系列文章目录
1.mybatis的初级使用
2.mybatis关于association的使用
文章目录
前言
记录学习mybatis关于事务方面的内容。
一、事务是什么?
事务是一个操作序列,它具有ACID四大特性。
- 原子性:整个操作过程要么全做,要么全不做。
- 一致性:事务按照预期生效,不管操作是成功,还是失败,数据的状态是人可以预期到的(数据库操作后的结果应该和人为推演一遍的结果一致)。
- 隔离性:不同的事务之间互不干扰。
- 持久性:一旦进行了操作,那操作的结果对数据库的改变是永久的。
二、mybatis事务的传播属性
当多个事务存在时,spring会采取的各种处理方式。
- Propagation.REQUIRED(required):如果当前有事务, 那么加入事务, 如果当前没有事务,则新建一个(Spring默认的选择)
- Propagation.NOT_SUPPORTED(not_supported) :如果当前存在事务就把当前事务挂起,执行完后恢复事务(忽略当前事务);
- Propagation.SUPPORTS (supports) :如果当前有事务则加入,没有则不用事务。
- Propagation.MANDATORY (mandatory) :如果当前没有事务,则抛出异常。(当前必须有事务)
- PROPAGATION_NEVER (never) :以非事务方式执行,如果当前存在事务,则抛出异常。(当前必须不能有事务)
Propagation.REQUIRES_NEW (requires_new) :如果当前有事务,则挂起当前事务,然后新创建一个事务。如果当前没有事务,则自己创建一个事务。
三、spring boot中使用事务
1.前提
想要在springboot中使用事务,有两大前提:
- 数据库的引擎需要支持事务。比如MySQL中InnoDB支持事务,而MyISAM是不支持的。
- 确保调用事务的方法是spring的代理对象,而不是真实的对象。直接用真实对象调用是不会触发事务的。(这种状况常发生在非事务方法的内部直接调用同一个类中的事务方法)
2.mybatis配置
pom.xml:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.3.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
</dependencies>
application.properties(喜欢用yml的,自己改成yml风格就行):
// 设置服务器端口,随便改
server.port=8081
// 配置jdbc(我用的是MySQL,其他数据库自己改一下)
spring.datasource.url = jdbc:mysql://localhost:3306/你的数据库名?setUnicode=true&characterEncoding=utf8&useSSL=false
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.data-username= 你的用户名
spring.datasource.data-password= 你的密码
// 配置mybatis的mapper.xml文件位置
mybatis.mapper-locations= org/example/mapper/*.xml
// 给实体类取别名,说白了就是以后在mapper.xml中声明实体类时不用指明路径了
mybatis.type-aliases-package= org.example.domain
3.写案例
这里简单模拟了一下新增订单案例。
1. 实体类
public class Order {
private Integer id;
private String status;
private String message;
}
2. mapper类
@Mapper
public interface OrderMapper {
List<Order> getAllInfo();
// 新增订单
void insertOne(Order order);
}
对应的xml文件:
<insert id="insertOne" parameterType="Order" useGeneratedKeys="true" keyProperty="id">
insert into order_tbl(status, message) values (#{status}, #{message})
</insert>
3. service实现类
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
OrderMapper orderMapper;
//插入一条订单,返回主键
private String addOrder(Order order) {
orderMapper.insertOne(order);
return order.getId().toString();
}
// 事务方法调用非事务方法时,非事务方法同样被加入事务中
@Transactional(rollbackFor = Exception.class)
@Override
public String create() {
Order order = new Order();
order.setMessage("无");
order.setStatus("未支付");
String orderId = addOrder(order);
// 主动设置的报错,事务只有在报错后才会回滚
int a = 1/0;
return "下单成功" + "主键为:" + orderId;
}
}
4. controller类
@RequestMapping("/order")
public class OrderController {
@Autowired
OrderService orderService;
@GetMapping("/add")
public String add() {
return orderService.create();
}
}
结果:在浏览器端访问后,会报分母为0的错,而数据库端是不会有新增数据的。但当去掉故意报错的那条语句后,数据库端会新增一条语句。
总结
记录单个事务回滚的使用过程。