一.整合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
  • 原理:
    1. 事务管理器TransactionManager,控制提交和回滚。
    2. 事务拦截器: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.隔离级别

  1. 读未提交(READ_UNCOMMITTED):能读未提交数据,有脏读问题,并发高但一致性差。
  2. 读已提交(READ_COMMITTED):只能读已提交数据,避免脏读,有不可重复读问题。
  3. 可重复读(REPEATABLE_READ):多次读同一数据结果一致,避免脏读和不可重复读,有幻读问题,mysql默认级别。
  4. 串行化(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等。。。),自己的设置失效

——————-事务篇结束——————–

天下繁华,唯有一心
最后更新于 2025-03-17