概念
事务指逻辑上的一组操作,组成这组操作的各个单元,要么全成功,要么全不成功。
从例子说起
待处理数据表之前
先不使用事务,代码如下.
import com.mchange.v2.c3p0.ComboPooledDataSource
object MysqlDemo extends App {
private val source = new ComboPooledDataSource()
private val connection: Connection = source.getConnection()
//connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ)
try {
//connection.setAutoCommit(false)
val ps: PreparedStatement = connection.prepareStatement("update emp set sal=sal+100 where empno='7369'")
ps.executeUpdate()
val i = 10 / 0
val ps1: PreparedStatement = connection.prepareStatement("update emp set sal=sal+100 where empno='7499'")
ps1.executeUpdate()
//connection.commit()
} catch {
case exception: Exception => {
exception.printStackTrace()
//connection.rollback()
}
}
connection.close()
}
执行后结果如下,其中一条指令执行,另一条没有执行. 不符合事务要求,
现在去掉代码中注释掉的事务语句,重新执行,结果不变,说明事务成功,遇到错误时启动了回滚.
object MysqlDemo extends App {
//创建连接池
private val source = new ComboPooledDataSource()
//从连接池中获取一个连接
private val connection: Connection = source.getConnection()
//设置隔离级别
connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ)
try {
//设置自动提交为false
connection.setAutoCommit(false)
val ps: PreparedStatement = connection.prepareStatement("update emp set sal=sal+100 where empno='7369'")
//执行更新数据
ps.executeUpdate()
//创造错误
val i = 10 / 0
//再次执行sql语句
val ps1: PreparedStatement = connection.prepareStatement("update emp set sal=sal+100 where empno='7499'")
ps1.executeUpdate()
//提交事务
connection.commit()
} catch {
case exception: Exception => {
exception.printStackTrace()
//发生异常时进行回滚
connection.rollback()
}
}
connection.close()
}
注释掉
val i = 10 / 0
再次执行全部成功
也就是验证事务的全部成功,要么全部失败的特性.
jdbc中的事务
这个是在代码中事务的应用方式
Connection的三个方法与事务有关:
setAutoCommit(boolean)
:设置是否为自动提交事务,如果true(默认值为true)表示自动提交,也就是每条执行的SQL语句都是一个单独的事务,如果设置为false,那么相当于开启了事务了;con.setAutoCommit(false) 表示开启事务。
commit()
:提交结束事务。
rollback()
:回滚结束事务。
Mysql中的事务
这个是在mysql查询界面用的,不是在代码中用的!
a、mysql引擎是支持事务的
b、mysql默认自动提交事务。每条语句都处在单独的事务中。
c、手动控制事务命令如下
开启事务:start transaction | begin
提交事务:commit
回滚事务:rollback
事务开始于
• 连接到数据库上,并执行一条DML语句insert、update或delete
• 前一个事务结束后,又输入了另一条DML语句
事务结束于
• 执行commit或rollback语句。
• 执行一条DDL语句,例如create table语句,在这种情况下,会自动执行commit语句。
• 执行一条DDL语句,例如grant语句,在这种情况下,会自动执行commit。
• 断开与数据库的连接
• 执行了一条DML语句,该语句却失败了,在这种情况中,会为这个无效的DML语句执行rollback语句。
事务的特性
原子性
指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
一致性
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。转账前和转账后的总金额不变。
拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
隔离性
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
持久性
指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误
PS:
以上代码需要导入C3P0以及mysql驱动
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
另外,C3P0的配置文件要放在工程的resource目录下.