JavaWeb: 事务与数据库连接池

来源:互联网 发布:linux 777 什么权限 编辑:程序博客网 时间:2024/06/05 06:59

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='陈少文';COMMITTRANSACTION;#两条语句同时执行成功,或者同时执行失败,保持一致性,需要使用事务包裹#关于事务的操作:开启事务,提交事务;#演示事务的回滚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);        //使用连接池操作数据库,没有什么难的。    }}

原创粉丝点击