JavaWeb: 事务与数据库连接池

Sql语句:

USE test;
CREATE TABLE t_account(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(20),
money INT
);

SELECT * FROM t_account;
INSERT INTO t_account VALUES(NULL,'陈如水',1000);
INSERT INTO t_account VALUES(NULL,'陈少文',1000);
DELETE FROM t_account WHERE id=2;
DELETE FROM t_account WHERE id=3;

#演示转账逻辑
START TRANSACTION;
UPDATE t_account SET money=money-100 WHERE NAME='陈如水';
UPDATE t_account SET money=money+100 WHERE NAME='陈少文';
COMMIT	TRANSACTION;
#两条语句同时执行成功,或者同时执行失败,保持一致性,需要使用事务包裹
#关于事务的操作:开启事务,提交事务;

#演示事务的回滚
START TRANSACTION;
UPDATE t_account SET money=money-100 WHERE NAME='陈如水';
UPDATE t_account SET money=money+100 WHERE NAME='陈少文';
ROLLBACK;-- 已经回滚,所以sql语句相当于不执行
COMMIT;
java代码:

package test;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * Created by Administrator on 2017/7/2.
 * 演示事务在jdbc中的使用
 */
public class TestTransaction {
    public static void main(String[] args){
        //演示转账业务逻辑
        try {
            Connection conn = DBUtils.getConnection();
            //打开事务,相当于start transaction
            conn.setAutoCommit(false);
            Statement st = conn.createStatement();
            st.executeUpdate("UPDATE t_account SET money=money-100 WHERE NAME='陈如水'");
            st.executeUpdate("UPDATE t_account SET money=money+100 WHERE NAME='陈少文'");
            //提交事务
            conn.commit();
            //回滚事务(相当于不执行上面的sql语句)
            //conn.rollback();
            DBUtils.close(conn,null,null);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}


事务

如果需要保证 两条sql语句要么同时成功,要么同时失败. 需要将这两个操作放置到一个事务中.

因为事务可以将多个sql语句"绑定"到一起执行.

 

核心语句:

1.打开事务 START TRANSACTION;

2.如果都成功了执行 = > 提交COMMIT;

3.如果任何一步出现问题 => 回滚 ROLLBACK; 表示sql语句执行不生效,事务结束。

 

事务的边界

1、默认情况下, mysql 在执行 每条sql语句时,都会自动打开一个事务,并在 语句执行之后立刻提交该事务 (自动提交事务);

2、为了将多条语句包裹到一个事务中, 我们就需要显式的打开事务(START TRANSACTION).这样数据库就不会自动提交事务,而是等待用户操作.

 

事务在mysql中的生命周期:

1. mysql数据库是自动事务提交的数据库. 每一条的运行都会默认(自动)开启一个事务,在语句执行成功后,自动提交事务.

2. 我们也可以使用start transaction 命令,手动控制事务.start transaction 命令代表事务打开.

3. start transaction 命令之后 , 事务结束: commit=> 代表语句执行生效,事务结束.

4. start transaction 命令之后 , 事务结束: rollback=> 代表语句执行(回滚)不生效,事务结束.

5. start transaction 命令之后 , 事务结束: 连接断开/宕机/超时,事务自动回滚.

事务的保存点:

相当于玩游戏的存档, 当一个业务 涉及多个语句 执行周期很长时, 我们可以在执行的过程中添加 保存点. 在后续的操作中,

如果出现执行失败, 就可以不用非得 回到最原点, 可以回到保存点. 节省时间。

 

事务在jdbc中的操作:

conn.setAutoCommit(true/false) => 打开/关闭 事务的自动提交  => 设置为false相当于执行了start transaction

conn.commit(); 事务的提交.

conn.rollback(); 事物的回滚.

保存点

conn.setSavePoint(String name);

conn.setSavePoint();  以上两个是添加保存点的方法

conn.rollback(SavePoint sp); 该方法指定还原到某保存点

 

事务的特性:

A Atomicity  原子性,事务中的操作将会被视为一个整体不可分割的部分,要么都成功要么都失败.

C Consistency一致性,事务执行前和执行后 数据的一致性应得以保证.例如tom账户减去100,相应的jerry账户就多出100;

I Isolation 隔离性,当同时存在多个事务的时候,事务之间应该不收干扰.

D Durability  持久性事务一旦提交,数据会持久化到保存介质上.

 

事务的并发性造成的问题

1、脏读=> A,B两个线程同时打开两个事务,A事务读取到了B事务修改但是还没有提交的数据.

2、不可重复读=> A在两次连续的读取某条数据时,b在两次读取之间,修改了a读取的数据并提交了事务. 导致A的两次读取得到的结果不一致.

3、幻读==> A在两次连续读取表中记录数量时,B在A第一次读取之后,插入了一条新的数据,导致A的两次读取数量不一致.

 

数据库的隔离级别

数据库对于以上三个问题,给出了解决方案:  InnoDB => 行锁

数据库准备了以下隔离级别来规避以上问题的产生.

读未提交 read uncommitted 1 脏读,不可重复读,幻读

读已提交 read committed 2 不可重复读,幻读

可重复读 repeatable read 4 幻读(mysql默认级别)

串行化 Serializable 8

oracle 还有一个自己定义的隔离级别,就是read only(只读) 级别;

 

数据库中的锁机制

数据库连接池

1,数据库连接池是什么? 应用程序与数据库建立连接的过程也是需要消耗资源的;如果不做任何处理,就需要不断的创建连接,关闭连接。,

2,连接池出现的必要性?每当需要访问数据库时,不在是创建连接,而是将连接从连接池中取出,直接使用即可;使用完毕后,将连接放回到连接池中,这样连接对象就可以复用,可以达到节省资源的目的。数据库连接池是用来提供连接复用的。

 

数据库连接池:1)初始化连接池中的连接,2)从连接池中获取连接

 

实现连接池分为两大步骤:

1.准备容器(连接池) 存放连接对象,每当有需要连接的时候,从容器中取出连接返回.

2.当连接关闭时, 不能真正连接关闭,而是需要连接收回.

 

dbcp连接池使用 (一般都是通过配置文件配置连接参数)

    //1> 直接new 连接池
    BasicDataSource dataSource =  new BasicDataSource();
    //2> 设置参数 
    // 驱动
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    // url
    dataSource.setUrl("jdbc:mysql:///day15");
    // userName
    dataSource.setUsername("root");
    //	password
    dataSource.setPassword("1234");
    
    //连接池中初始化多个连接
    dataSource.setInitialSize(3);
    //设置最大空闲连接数
    dataSource.setMaxIdle(10);
    //设置最小空闲连接数
    dataSource.setMinIdle(3);

c3p0连接池使用(这两种连接池的使用)

package test;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mchange.v2.c3p0.DataSources;

import java.sql.SQLException;

/**
 * Created by Administrator on 2017/7/3.
 */
public class TestConnPool {

    //测试c3p0连接池
    public void fun1() throws SQLException {
        //配置的名称必须是固定的 c3p0-config.xml
        ComboPooledDataSource ds = new ComboPooledDataSource();

        //使用完毕后销毁数据库连接池
        DataSources.destroy(ds);
        //使用连接池操作数据库,没有什么难的。
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值