一.整合jdbc和数据源
1.基本概念
DataSource:Java 标准接口,负责管理数据库连接,像配置连接池、获取物理连接。 JdbcTemplate:Spring 工具类,基于 DataSource 简化 JDBC 操作,处理 SQL 执行和结果集
2.导入依赖
mysql驱动 和 jdbc
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
3.配置环境
在application.properties中书写
spring.datasource.url=jdbc:mysql://localhost:3306/数据名称
spring.datasource.username=用户名
spring.datasource.password=密码
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
配置好后,就可以使用JdbcTemplate与数据库进行交互了
jdbcTemplate内置了对数据库增删改查的操作
二.一些实验
1.queryForObject(查)
//通过id查询图书
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Book.class), id);
2.update(增删改)
比如:增加图书
public void addBook (Book book) {
String sql = "insert into book(bookName,price,stock) values (?,?,?)";
jdbcTemplate.update(sql,book.getBookName(),book.getPrice(),book.getStock());
}
3.汇总
其中问号类似于占位符,可添加多个
@Component
public class BookDao {
@Autowired
JdbcTemplate jdbcTemplate;
//根据id查询
public Book getBookById(Integer id) {
String sql = "select * from book where id = ?";
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Book.class), id);
return book;
}
//根据id修改
public void updateStock(Integer id) {
String sql = "update book set stock = stock - 1 where id = ?";
jdbcTemplate.update(sql, id);
}
//插入
public void insert(Book book) {
String sql = "insert into book(book_name,price,stock) values(?,?,?)";
jdbcTemplate.update(sql, book.getBookName(), book.getPrice(), book.getStock());
}
//根据id删除
public void delete(Integer id) {
String sql = "delete from book where id =?";
jdbcTemplate.update(sql, id);
}
}
三.@Transactional事务绑定
1.事务管理器原理
transactionManager:事务管理器
控制事务的获取、提交、回滚。
- 底层默认使用哪个事务管理器?默认使用
JdbcTransactionManager
。 - 原理:
- 事务管理器:
TransactionManager
,控制提交和回滚。 - 事务拦截器:
TransactionInterceptor
,控制何时提交和回滚completeTransactionAfterThrowing(txInfo, ex);
在这个时候回滚。
- 事务管理器:
commitTransactionAfterReturning(txInfo);
在这个时候提交。
2.开启事务
在主类上方添加注解,开启事务自动化管理
@EnableTransactionManagement
在方法上添加注解,为方法添加事务
@Transactional
3.timeout超时控制
@Transactional(timeout = 3)
限制从方法开始到最后一次执行Dao操作的时间
4.readOnly只读优化
当事务只涉及读的操作,开启后会进行一些优化操作
@Transaction(readOnly = true)
5.rollbackFor指明回滚异常
不是所有异常都一定引起事务回滚
异常:
- 运行时异常(unchecked exception【非受检异常】)
- 编译时异常(checked exception【受检异常】)
回滚默认机制:
- 运行时异常:回滚
- 编译时异常:不回滚
手动指明异常回滚
@Transcation(rollbackFor = {IOException.class})
或者
@Transcation(rollbackForClassName = "IOException")
手动指明异常不会滚
@Transcation(noRollbackFor = {IOException.class})
或者
@Transcation(noRollbackForClassName = "IOException")
6.隔离级别
- 读未提交(READ_UNCOMMITTED):能读未提交数据,有脏读问题,并发高但一致性差。
- 读已提交(READ_COMMITTED):只能读已提交数据,避免脏读,有不可重复读问题。
- 可重复读(REPEATABLE_READ):多次读同一数据结果一致,避免脏读和不可重复读,有幻读问题,mysql默认级别。
- 串行化(SERIALIZABLE):事务依次执行,无并发问题,数据一致性最高,但并发性能最差。

补充:
脏读(Dirty Read)是数据库并发操作中出现的一种问题,指一个事务读取到了另一个事务未提交的数据。由于未提交的数据可能会被回滚,所以读取到的这些数据可能是无效的、“脏”的,这就违背了数据的一致性原则。
幻读(Phantom Read)是数据库并发控制中的一种现象,它发生在一个事务内多次执行相同的查询时,由于其他事务插入或删除了符合查询条件的记录,导致该事务在不同时间点执行相同查询得到的结果集不一致,就好像出现了“幻影”记录一样
不可重复读(Non-Repeatable Read)是数据库并发操作中出现的一种问题。它指的是在一个事务内,多次读取同一数据时,由于其他事务对该数据进行了修改并提交,导致每次读取的结果不一致
注解
@Transactional(isolation = Isolation.REPEATABLE_READ)
7.事务传播行为
定义:当一个事务方法被另一个事务方法调用的时候,事务该以何种方式存在?事务属性该如何传播下去?
Spring 事务管理有 7 种传播行为:
传播行为 | 产生效果 |
REQUIRED(默认) | 有事务则加入,无则创建新事务。 |
SUPPORTS | 有事务加入,无则非事务执行。 |
MANDATORY | 有事务加入,无则抛异常。 |
REQUIRES_NEW | 无论有无,都创建新事务,挂起当前事务。 |
NOT_SUPPORTED | 非事务执行,有事务则挂起 |
NEVER | 非事务执行,有事务抛异常。 |
NESTED | 有事务则嵌套执行,无则创建新事务。 |
参数设置项也会传播(当小事务和大事务公用一个事务时:比如REQUIRED,小事务会沿用大事务的参数设置项(timeout等。。。),自己的设置失效
——————-事务篇结束——————–
Comments NOTHING