连接池&事务管理

连接池、事务管理以及事务的传播行为的笔记。

一、连接池:

        1.使用连接池的原因:

                     Java程序操作数据库,必须获得一个连接Connection。
                      实际操作中,先获得连接,使用完成关闭连接。这两个操作都比较耗时。

        2.定义:

                    一组连接组成的一个池子(集合),称为连接池。

        3.工作原理:

                       连接池&事务管理_第1张图片

         4.使用规范: 

                     JavaEE规范规定,连接池必须实现 `javax.sql.DataSource`

                     接口中规定方法:getConnection()

         5.常见的第三方连接池:

                        druid,德鲁伊,alibaba提供,稳定,性能好等
                        DBCP,Apache提供,tomcat内置
                        C3P0,hibernate框架底层使用。(等效框架MyBatis)

           6.入门案例:

                      1.导入坐标:

连接池&事务管理_第2张图片

                  2. 测试类:

package com.czxy;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import org.junit.Test;

import java.sql.SQLException;

/**
 * @Author: 小新
 * @Date: 2021-12-03 08:49
 */
public class TestDruid {

    @Test
    public void run() throws SQLException {
        //1.获得连接池
        //1.1核心类
        DruidDataSource dataSource = new DruidDataSource();
        //1.2基本四项
        //1) 驱动
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        //2)链接url
        dataSource.setUrl("jdbc:mysql://localhost:3306/db_20211028");
        //3)用户名
        dataSource.setUsername("root");
        //4)密码
        dataSource.setPassword("1234");

        //1.3特殊项【可选】
        //1)初始化大小
        dataSource.setInitialSize(5);
        //2)最大值活动数
        dataSource.setMaxActive(10);
        //3)最小值空闲数
        dataSource.setMinIdle(2);

        //2.从连接池中获得链接
        DruidPooledConnection conn1 = dataSource.getConnection();
        System.out.println(conn1);
        conn1.close();

        DruidPooledConnection conn2 = dataSource.getConnection();
        System.out.println(conn2);
        conn2.close();
    }
}

                       3.测试结果:

测试一:

代码:

连接池&事务管理_第3张图片

 结果:连接池&事务管理_第4张图片

 测试二:

代码: 

连接池&事务管理_第5张图片

结果: 

连接池&事务管理_第6张图片

二、事务管理:

         1.回顾事务:

                1.1 事务定义:

                                在数据库开发中,一组业务逻辑,要么全部成功,要么全部失败。

                1.2事务的作用:

                             保证一组操作要么全都成功,对数据库进行完整更新。要么在某一个动作失败的时候让数据恢复原状,不会引起不完整的修改。

                1.3事务特性(ACID):          

                         ①原子性(Atomicity)原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

                         ②一致性(Consistency)事务前后数据的完整性必须保持一致。

                         ③ 隔离性(Isolation)事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。

                         ④持久性(Durability)持久性是指一个事务一旦被提交,它对数据库中数据的改变 就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

                1.4事务隔离问题:

                            ①脏读:一个事务读到了另一个没有提交的数据。

                            ②不可重复读:一个事务读到了另一个事务已有提交的数据(update)。

                            ③幻读:一个事务读到了另一个事务已有提交的数据(insert)。

                 1.5隔离级别:

                           ①读未提交(read uncommitted):一个事务读到另一个事务没有提交的数据。存在3个问题,解决0个问题。

                           ②读已提交(read committed):一个事务读到另一个事务已经提交的数据。存在2个问题,解决1个问题(脏读)。

                           ③可重复读(repeatable read):在一个事务中读到的数据重复的。存在1个问题,解决2两个问题(脏读、不可重复读)。

                           ④串行化(Serializable):单事务。存在0个问题,解决3三个问题(脏读、不可重复读、幻读)。

                 1.6 性能&安全对比:

                             性能:read uncommitted > read committed > repeatable read > Serializable

                             安全:read uncommitted < read committed < repeatable read < Serializable

                 1.7默认隔离级别:

                             mysql:可重复读(repeatable read)
                             Oracle:读已提交(read committed)

            2.事务详解:

                 2.1传播行为:

                            概述:一个事务调用另一个事务,事务共享问题。

传播行为 描述 举例
PROPAGATION_REQUIRED,required 支持当前事务,如果没有事务,创建一个新的。

A 有事务,B使用A的事务。(支持当前事务)

A没有事务,B创建新的。()

PROPAGATION_SUPPORTS,supports 支持当前事务,如果没有事务,以非事务执行。

A 有事务,B使用A的事务。(支持当前事务)

A没有事务,B以非事务执行。

PROPAGATION_MANDATORY,mandatory 支持当前事务,如果没有事务,抛异常

A 有事务,B使用A的事务。(支持当前事务)

A没有事务,B抛异常。

PROPAGATION_REQUIRES_NEW,requires_new 创建一个新事物,如果当前有事务,将挂起

A 有事务,B创建新事务,同时挂起A事务。

A 没有事务,B创建新事务。

PROPAGATION_NOT_SUPPORTED, not_supported 不支持当前事务,以非事务执行,如果有挂起

A 有事务,B以非事务执行,同时挂起A事务。

A 没有事务,B以非事务执行。

PROPAGATION_NEVER, never 不支持当前事务,如果有抛异常。

A 有事务,B抛异常

A 没有事务,B以非事务执行。

        
PROPAGATION_NESTED, nested 嵌套事务,底层使用savepoint进行嵌套事务操作。 保存点允许回顾部分事务 。

连接池&事务管理_第7张图片

           3.事务详解配置:

                       @Transactional 注解可以描述事务定义,一般情况默认值最常用。

@Transactional(
    readOnly = false,
    timeout = -1,
    isolation = Isolation.DEFAULT, 
    ropagation = Propagation.REQUIRED)

          4.入门案例: 

                   4.1 需求 :完成转账功能。

                   4.2 表结构:

CREATE TABLE account(
  id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR(40),
  money FLOAT
);
insert into account (id,name,money) values('1','jack','10000');
insert into account (id,name,money) values('2','rose','10000');

                 4.3 项目结构:

连接池&事务管理_第8张图片

                4.4 实现:

mybatis配置类:

@Configuration
public class MyBatisConfiguration {

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        //1 创建工厂
        // 1.通过工厂bean创建对象,最后需要调用 getObject()获得具体的对象
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();

        //2 设置数据-- SqlMapConfig.xml 配置信息

        // 1.1 设置数据源
        factoryBean.setDataSource(dataSource);
        // 1.2 设置别名包扫描
        factoryBean.setTypeAliasesPackage("com.czxy.demo17_tx.domain");
        // 1.3 全局配置:驼峰映射
        org.apache.ibatis.session.Configuration config = new org.apache.ibatis.session.Configuration();
        config.setMapUnderscoreToCamelCase(true);
        factoryBean.setConfiguration(config);

        // 2 插件配置
        // 2.1 分页插件
        PageHelper pageHelper = new PageHelper();
        Properties pageProps = new Properties();
        pageProps.setProperty("dialect", "mysql");
        pageProps.setProperty("rowBoundsWithCount", "true");
        pageHelper.setProperties(pageProps);
        factoryBean.setPlugins(new Interceptor[] { pageHelper });


        // 返回SqlSessionFactory
        return factoryBean.getObject();
    }

    /**
     * 扫描Dao的包,查找各种XxxMapper接口,创建好UserMapper等对象存入到IOC的容器中
     * @return
     */
    @Bean
    public MapperScannerConfigurer mapperScanner() {
        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
        configurer.setBasePackage("com.czxy.demo17_tx.mapper");
        return configurer;
    }

}

Spring配置类:

@Configuration
@PropertySource("classpath:db.properties")
@ComponentScan(basePackages = "com.czxy.demo17_tx")
@EnableTransactionManagement            //开启事务管理
public class SpringConfiguration {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String username;
    @Value("${jdbc.password}")
    private String password;

    /**
     * 连接池配置
     * @return
     */
    @Bean
    public DataSource dataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(driver);
        druidDataSource.setUrl(url);
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);

        return druidDataSource;
    }

    /**
     * 平台事务管理器
     * @param dataSource
     * @return
     */
    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

domain:

public class Account {
    @Id
    private Integer id;
    private String name;
    private Float money;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Float getMoney() {
        return money;
    }

    public void setMoney(Float money) {
        this.money = money;
    }
}

mapper:

public interface AccountMapper extends Mapper {
}

service接口及方法:

public interface AccountService {
    /**
     * 转账
     * @param outId
     * @param inId
     * @param money
     */
    public void change(int outId, int inId, float money);
}

service实现类:

@Service
@Transactional(timeout = 10,readOnly = false, isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED)      //事务定义
public class AccountServiceImpl implements AccountService {
    @Resource
    private AccountMapper accountMapper;

    @Override
    public void change(int outId, int inId, float money) {
        //汇款 -
        Account outAccount = accountMapper.selectByPrimaryKey(outId);
        outAccount.setMoney( outAccount.getMoney() - money);
        accountMapper.updateByPrimaryKey(outAccount);

        //模拟异常
//        int i = 1/0;

        //收款 +
        Account inAccount = accountMapper.selectByPrimaryKey(inId);
        inAccount.setMoney( inAccount.getMoney() + money);
        accountMapper.updateByPrimaryKey(inAccount);
    }
}

Test测试类:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {SpringConfiguration.class, MyBatisConfiguration.class})
public class TestDemo17Tx {
    @Resource
    private AccountService accountService;

    @Test
    public void testDemo() {
        accountService.change(1,2,100);
        System.out.println("转账成功");
    }
}

测试结果:

ider:

连接池&事务管理_第9张图片

数据库:

 

你可能感兴趣的:(Spring,java,maven,spring)