Jdbc事务

Jdbc中事务操作介绍

事务操作的方法.

setAutoCommit(false)相当于start transaction;开启事务

rollback()事务回滚

commit()事务提交

设置事务的回滚点

例如:

Savepoint sp = conn.setSavepoint();

conn.rollback(sp);

事务特性(ACID)-----笔试题

原子性:指它是一个不可分割的整体,要么全都成功,要么全都不成功。

一致性:在执行事务完成后,前后的数据要保持一致。

隔离性:事务与事务之间不可以相互影响。

持久性:事务一旦提交,数据就真正修改了,不可以在改变。

关于事务隔离性问题

不考虑隔离性会产生什么问题?

1. 脏读  一个事务读取到了另一个事务的未提交数据。

2. 不可重复读  一个事务多次读取结果不一致。(一个事务读取到了另一个事务提交的数据) 这个强调的update.  

3. 虚读(幻读一个事务多次读取结果不一致 这个强调的是insert操作

4. 丢失更新  后提交事务的修改操作将先提交的事务的修改操作覆盖。

对于以上问题,怎样进行控制?可以通过设置事务的隔离级别来解决以上问题

设置事务隔离级别

事务隔离级别有四种----------(级别从高到低)

1 Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)

2 Repeatable read:可避免脏读、不可重复读情况的发生。(可重复读)不可以避免虚读

3  Read committed:可避免脏读情况发生(读已提交)

4 Read uncommitted:最低级别,以上情况均无法保证。(读未提交)

 

Mysql数据库默认的事务隔离级别是 repeatable read

Oracle数据库默认的事务隔离级别是 read committed 

设置事务的隔离级别:

Mysql设置

数据库默认有事务的隔离级别,mysql 中查看与修改事务的隔离级别

set session transaction isolation level 设置事务隔离级别

select @@tx_isolation 查询当前事务隔离级别

jdbc中设置

这个方法是在jdbc中设置事务的隔离级别

参数level可以是以下值之一

Connection.TRANSACTION_READ_UNCOMMITTED(最低)、

Connection.TRANSACTION_READ_COMMITTED(次低)

Connection.TRANSACTION_REPEATABLE_READ(次高) Connection.TRANSACTION_SERIALIZABLE。(最高)

(注意,不能使用 Connection.TRANSACTION_NONE,因为它指定了不受支持的事务。)

演示不考虑事务隔离级别产生问题及解决方案

----演示脏读及解决方案

一个事务读取到了另一个事务的未提交数据。

要想演示脏读,我们必须设置事务的隔离级别Read uncommitted

步骤

1.设置两个窗口的事务隔离级别

set session transaction isolation level Read uncommitted;

2.在两个窗口中开启事务

start transaction;

3.在 A窗口中执行汇款操作(但没有提交事务,可以回滚)

Jdbc事务

4.在b窗口中执行(看到的结果是对方未提交的事务)

Jdbc事务

出现了脏读。

解决脏读,可以设置事务隔离级别为Read committed(次级)

1. 设置事务隔离级别

set session transaction isolation level Read committed;

将上面操作在执行一次。

2. 这时b窗口在执行查询操作结果

Jdbc事务  

解决了脏读。

 

----演示不可重复读

没有脏读,读取前是对方未提交的数据(正常的),过一会再查变成对方提交后的数据,两次读取数据不一样

不可重复读是指一个事务读取到了另一个事务提交的数据。

接着上面的案例继续执行。

1. A窗口将事务提交。

2. B窗口在查询数据

Jdbc事务  

----解决不可重复读

将事务的隔离级别修改为Repeatable read(次高)

 

1. 将事务隔离级别修改为

set session transaction isolation level Repeatable read;

2. 将上述操作在执行一次,那么会发现,我们在执行查询结果

Jdbc事务  

这时A窗口已经commit.但我们没有读取到提交的数据。

避免了不可重复读。(但数据真实性没有得到及时更新)(保证在自己当前事务的查到数据一致)

要想将A窗口提交的数据读取到,必须让当前事务commit,在执行操作 

设置事务隔离级别为Serializable

set session transaction isolation level Serializable;

这种事务隔离级别会锁表,它的安全性最高。(只允许一个事务操作,其他事务只能等待操作) 

对于隔离级别四种

安全性  Serializable》Repeatable read》read committed 》read uncommitted;

性能  Serializable《Repeatable read《read committed 《read uncommitted;

开发中,一般使用  read committed  repeatable read两种。

 

案例-转帐汇款操作

通过这个案例明白service层的作用,及在开发中,事务一般都是在service层处理的。

Jdbc事务  

1. 创建一个account.jsp页面

Jdbc事务  

2. 创建一个AccountServlet

Jdbc事务  

3. 创建一个AccountService

1. 开启事务 

2. 调用dao中两个方法完成转账汇款操作

3. 有问题了在catch中进行事务 回滚。

4. 最后在finally中进行事务commit及con.close();

简单说,我们在service层调用了dao中两个方法,为了保证这个两个操作是在同一个事务中,我们将Connection做为参数传递到了dao层。

 

4.创建一个AccountDao

在dao中进行转账汇款操作

在以上代码基础上进行优化

1. 对jdbcUtils工具进行优化

2. 对service层传递connection对象到dao进行优化。


ThreadLocal类,它相当于一个Map集合,只不过它的key就是当前线程对象.

通过set方法向ThreadLocal中添加元素  相当于put(Thread.currentThread(),Object);

通过get方法从ThreadLocal中获取元素   相当于get(Thread.currentThread());

 

在jdbcUtils中创建一个ThreadLocal对象来存储绑定到线程中的Connection对象,在JdbcUtils中提供开启事务,事务回滚,事务提交及关闭的方法

Jdbc事务  

 

Jdbc事务  

什么是丢失更新

丢失更新是指后提交的事务将先提交事务的修改操作覆盖了。

Jdbc事务

解决丢失更新问题方式:

1. 悲观锁   for update(排它锁) update语句默认添加排它锁。

2. 乐观锁  使用版本字段

 

 

 

 

 

 

 

 



来自为知笔记(Wiz)


你可能感兴趣的:(Jdbc事务)