环境搭建 spring配置数据库
- 1.在pom.xml安装相应的依赖
- 2.在properties里面配置数据库的相关信息,需要强调的一点是,一定不要在properties里面添加任何空格,否则就会像我一样搞了两小时,数据一直报错,然后发现是空格的问题。
JdbCTemplate的查询操作
JdbcTemplate的插入操作
需要注意的是,一定把book(value1,value2,value3)写全,不然会报错
插入成功
JdbcTemplate的更新操作
类似于插入,直接用update去执行语法即刻
JdbcTemplate的删除操作
删除Id为1的图书
JdbcTemplate的复杂逻辑
编写Service接口
编写ServiceImpl接口
测试
使用事务
在主函数文件上方加一个@EnableTransactionManagement注解,表示开启事务管理
Spring03TxApplication.java
package com.atguigu.spring03tx;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement //开启事务管理
@SpringBootApplication
public class Spring03TxApplication {
@Autowired
JdbcTemplate jdbcTemplate;
public static void main(String[] args) {
SpringApplication.run(Spring03TxApplication.class, args);
}
}
UserServiceImpl代码
package com.atguigu.spring03tx.service.impl;
import com.atguigu.spring03tx.Bean.Book;
import com.atguigu.spring03tx.dao.AccountDao;
import com.atguigu.spring03tx.dao.BookDao;
import com.atguigu.spring03tx.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
@Service
public class UserServiceImpl implements UserService {
@Autowired
BookDao bookDao;
@Autowired
AccountDao accountDao;
@Transactional //在这个地方加上Transactional注解
@Override
public void checkout(String username, Integer bookId, Integer buyNumber) {
Book book = bookDao.getBookbyId(bookId);
BigDecimal price = book.getPrice();
BigDecimal total = price.multiply(new BigDecimal(buyNumber));
accountDao.updateBalanceByUsername(username, total);
bookDao.updateBookStock(bookId, buyNumber);
int i = 1 / 0;
}
}
可以发现Book和Account都没有执行代码,即出现了回滚操作。
事务的超时
service代码如下,在transaction中添加了timeout=3表示超过3s就报超时错误,然后在代码中出现了睡眠3s,所以会出现超时,不会对数据造成改变
rollbackFor
先编写一个找不到指定文件的IO异常
然后查看数据库,库存由97变为94,执行成功,没有回滚
原理如下:运行时回滚,编译时不会滚
rollbackFor可以指定哪些异常需要回滚,加上这句话就可以回滚了,norollbackFor同理
事务的隔离级别
三个可能出现的问题,首先了解以下事务是什么,类似于一个函数,里面有很多代码,使用代码的时候相当于事务的开始,代码结束的时候相当于事务的提交
脏读:脏读就是事务A在事务B未提交的时候,读了事务B修改的数据,但是事务B发生了回滚,事务A读取的数据就是脏数据。因为数据被污染了,所以称脏数据。解决措施:读已提交,因为根源是未提交会出现回滚。
不可重复读:一般来说发生在修改阶段,事务A之前读取过一个数据,但是中间事务B开始,修改该数据,直到结束(已提交),然后事务A再次读取数据的时候,和之前读取的数据不一样了。采取措施是对行数据上锁。
幻读,一般来说是表示事务A 按照一定条件进行数据读取, 期间事务B 插入了相同搜索条件的新数据,事务A再次按照原先条件进行读取时,发现了事务B 新插入的数据称为幻读。
解决措施:这个情况和可重复读类似,但是可重复读针对的是对行数据上锁。但是幻读发生在表上,也就是说事务A和B对表的增删是不互斥的,所以事务B增删行之后,对事务A产生了幻读。所以采取的措施是对表上锁,表只能被一个事务执行,也就是最高级别序列化。
Propagation
传播行为
在 Spring 框架中,propagation(事务传播行为) 是事务管理的核心概念之一,用于定义当一个事务方法被另一个事务方法调用时,事务如何传播和处理。通过设置不同的传播行为,可以控制多个嵌套事务的边界和行为,确保数据一致性和业务逻辑正确性。
就是控制调用者和被调用者之间的关系,属性通常写在被调用者的函数上面。
被调用者
调用者
接下来是传播行为的几大类别
最常见的是REQUIRED,使用这个之后,被调用的事务就变为调用者事务的一部分,被调用者的属性全部失效。