学习Java Web 基础篇,可以熟练的完成对数据库的增删改查等基本操作,该篇讲解JDBC 的高级用法,包括事务处理,连接池,这些技术构成了JAVA Web 分层开发中持久层的核心要件,是Java 程序操作数据库的重要支撑。
数据库的事务:
1.事务的概念:
事务,是指数据库中的一个操作序列,它由一条或多条SQL 命令所组成,这些SQL 命令不可分割,只有当事务中所有的SQL 命令被成功执行后,整个事务引发的操作才能被更新到数据库。
如下面两条Sql语句(李磊购物需要向商家支付500的事务):
Update account Set money=money-500 Where name= "lilei";
Update account Set money=money+500 where name="shop";
这两条 Sql 命令属于同一个操作序列,只有全部成功执行时,整个事务才会被更新到数据库,否则,全部SQL命令都要被取消,这就避免了李磊账户上面少了500元而商家账户金额不变的情况。
Mysql 数据库共有两种方式来管理事务:
1.自动提交事务
默认状态下,MySQL 自动提交事务,即每执行一条SQL 语句就提交一次事务,可以通过Mysql 全局变量 autocommit 进行查看,SQl 语句如下:
Show Variables like '%commit%';
通过Sql 语句查看当前数据库的事务状态,执行结果如下:
从以上的执行结果可以看出,autocommit 的值为 On,这时,数据库事务是默认提交的。
关闭数据库自动提交事务的功能,SQL 语句如下:
Set AutoCommit=0; # 0 是 OFF,1是 ON
当 autocommit 显示为OFF 状态是需要手动提交,手动提交事务,首先要开启事务(Start Transaction),再提交( Commit)或回滚(Rollback) 事务。提交事务回将整个事务中的操作更新到数据库,回滚事务则会取消整个事务中已执行的所有操作,当手动提交事务时,上文实例中购物支付触发的Sql 语句如下:
START TRANSACTION # 开启事务
Update account SET money =money-500 where name ="lilei";
Update account SET money =money+500 where name='shop'
COMMIT; # 提交事务
# 或者 (提交或回滚二选一)
ROLLBACK #回滚事务
2.事务的ACID 属性
ACID,是数据库事务正确执行的四个基本要素的缩写,它包含原子性(Atomicity)一致性(Consistency),隔离性(Isolation),持久性(Durability),一个支持事务的数据库,必须要具备这四种特性,否则在事务管理中无法保证数据的正确性。
原子性:整个事务中所有的操作都是不可分割的,要么完全执行,要么完全不执行,不能停留在中间某个环节,事务的操作序列如果全部成功,就必须完全应用到数据库,如果有一项操作失败,就不能对数据库有任何影响。
一致性:事务完成时,数据必须是一致的,即与事务开始之前,数据存储中的数据处于一致状态,保证数据的无损,如转账为例,两个账户中的总数不能变。
隔离性:隔离性是指事务之间相互独立,彼此隔离,当多个用户访问数据库时,如操作同一张表,数据库为每一个用户开启的事务,不能被其他事务所干扰。
持久性:持久性是指事务一旦提交,那么对数据库中的数据的改变就是永久性的,即使数据库系统遇到故障也不会丢失事务的处理效果。
3.数据库的隔离级别:
对数据库而言,最明显的特征是资源可以被多个用户共享,当相同的数据库资源被多个用户(多个事务)同时访问时,如果没有采取必要的隔离措施,就会导致各种并发问题,破坏数据的完整性。
如果不考虑隔离性,数据库将会存在如下三种并发问题:
1.脏读
一个事务读到了另一个事务尚未提交的更改数据
2.不可重复读
不可重复读是指一个事务读取数据后,另一个事务执行更新操作,使第一个事务无法再现前一次的读取结果。
3.幻读
幻读是指一个事务读取数据后,另一个事务执行插入操作,使第一个事务无法再现前一次的读取结果,例如,事务T1 两次统计所有账户的总金额,在这期间,事务T2 插入了一条新记录,是的两次统计的金额不一致。
为了解决并发造成的问题,数据库规范定义了4种隔离级别,用于限定事务之间的可见性,不同的事务隔离级别对应的解决数据并发问题的能力是不同的:
read uncommitted: 一个事务读取到另一个事务没有提交的数据
read committed:一个事务读到另一个事务提交后的数据
repeatable read(可重复读): 在一个事务中读到的数据始终一致,无论其他事务是否提交
serializable:只能同时执行一个事务,相当于事务中的单线程
以上4中隔离级别中,安全性最高的是Serializable (串行化),最低点是 read uncommitted (读未提交),当然,安全性能越高,执行效率就越低,serilizable这样的级别,就是以锁表的形式,使其他事务只能锁在外边等待,所以平时选用何种隔离级别应该根据实际情况来定。Mysql数据库默认的隔离级别为repetable read。
4.JDBC 实现事务处理:
在JDBC 的数据库操作中,Connection 对象为事务管理提供了如下3个方法:
setAutoCommit(boolean autocommit):设置是否自动提交事务
commit() :提交事务
rollback():回滚
默认情况下,JDBC 的事务是自动提交的,一条数据库的更新表达式代表一项事务,操作成功后,系统将自动调用commit()来提交,否则将调用rollback()来回滚
public class TestPayMent {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/chapter02", "root", "123456");
//关闭事务的自动提交
conn.setAutoCommit(false);
//lilei 的账户减去100元
PreparedStatement pst= conn.prepareStatement("UPDATE account SET money=money-100 where aname=?");
pst.setString(1,"lilei");
pst.executeUpdate();
PreparedStatement pst2= conn.prepareStatement("UPDATE account SET money=money+100 where aname=?");
pst2.setString(1,"shop");
pst2.executeUpdate();
//提交事务
conn.commit();
}
}
代码执行完毕后,再次发送select 语句,JDBC 已将本次事务引发的操作提交到数据库中:
数据库的连接池:
1.