JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils

一. 事务 Transaction

1. 事务

是什么?
其实是一组操作,里面包含许多个单一的逻辑。只要有一个逻辑没有执行成功,那么都算失败。所有数据都回到最初的状态(回滚)。

作用
为了确保逻辑的成功
例子:银行的转账操作,中间过程只要出问题就转账失败,回到最初的状态。

2. 演示事务

(1) 使用命令行演示事务
  • 开启事务

start transaction
JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第1张图片
此时,数据并没有写入数据库内存。

  • 提交或回滚事务

commit:提交事务,数据会写到磁盘上的数据库
当执行commit命令后,数据才会被写入内存
rollback: 数据回滚,回到最初的状态
执行rollback命令后,数据的内容回到最初的状态
JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第2张图片
注意,需要在mysql中关闭自动提交的功能
JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第3张图片
从start transanction 到提交事务或者回滚事务代表一个事务的结束,只针对当前连接对象

(2). 使用代码演示事务

代码如下:
JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第4张图片

代码中由于int a = 10/0 存在异常,因此事务的所有操作并没有执行完成,因此调用catch中的rollback的方法,回到最初的状态。

3. 事务的特性

ACID

  • 原子性

事务包含的逻辑不可分割

  • 一致性

数据执行前后,保持数据完整性

  • 隔离性

事务执行期间不一应该受到其他事务的影响

  • 持久性

事务执行成功,数据必须永久的保存在磁盘上

4. 事务的安全隐患

不考虑隔离级别设置,会出现以下问题

  • 读的问题

(1) 脏读:一个事务读到另外一个事务还未提交的数据
(2) 不可重复读:一个事务读到了另外一个事务提交的数据,造成前后两次查询结果不一致(针对updata)
(3) 幻读: 一个事务中,两次查询结果不一致(针对insert)。

  • 读的级别

(1) 读未提交:容易造成脏读
(2) 读已提交:解决脏读 造成不可重复读>
(3) 可重复读: 解决不可重复读 造成幻读
(4) 可串行化: 读的问题都解决。如果有一个隔离级别设置了可串行化,那么谁先打开事务,谁就有先执行的权利,其他事务只能等着,前面的事务提交或者回滚之后,后面的事务才能执行,这种隔离级别一般少用,容易造成性能上的问题,效率比较低下。

  • 写的问题

丢失更新
两个人同时操作一条数据,以最后操作时间的更新为准,会造成前一个人更新的数据丢失。
JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第5张图片

  • 丢失更新问题的解决

悲观锁
认为丢失更新问题一定会出现
使用语句 select * from 表名 for update; for update 数据库的锁机制,排他锁。
JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第6张图片

乐观锁
需要程序员自己写代码实现
通过给事务和数据库进行设置标记,如果标记相同就允许其修改,反之,则需要重新查询数据。JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第7张图片

二. 数据库连接池

1.是什么

由于数据库的连接对象创建工作比较消耗性能。
为了解决此类问题,可以一开始在内存中开辟一块空间(集合),一开始在池子里放至多个连接对象,后面需要连接的话,直接从池子里面取就行了。使用完毕,一定要归还,确保连接对象的循环使用。

2. 怎么用

(1) 自定义数据库连接池

DataSource : sun公司针对数据库连接池定义的一套规范
代码如下JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第8张图片自定义数据库连接池代码的问题
(1)需要额外记住addBack()方法
(2)无法面向接口编程,因为接口里面没有addBack()的方法
(3)需要创建多个连接池对象

  • 解决方法

为了体现面向接口编程的方法,有以下解决方法
(1) 直接修改源码 不现实
(2) 继承需要修改扩展方法的这个类,然后重写这个方法
由于connection接口里没有addBack这个方法,并且不知道在数据库连接中具体实现connection接口的是哪个类,没有办法采用继承来重写close方法进行扩展。因此这两个解决办法都不可以。

可以使用设计模式中的装饰者模式解决

如果不了解装饰者设计模式,请点击以下链接了解
设计模式之装饰者模式

装饰类代码

JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第9张图片

这里实现了connection接口,并重写了其中的close方法和preparestatement方法。当掉用close方法时,不再是关闭连接,而是将该连接还给数据库连接池,由于使用该连接时,需要用到prepartstatement方法,因此也需要重写这个方法。只需要将传进来的connection对象的preparestatement返回就可以了。

具体的实现

JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第10张图片

当调取getConnection方法时,我们返回一个利用ConnectionWrap包装后的connection对象。当我们在使用完数据库连接时,调用该连接的close方法时,它就执行了我们包装类中的close方法,将该连接返回给数据库连接池。

(2) 开源的数据库连接池

自定义数据库连接池开发效率低,迁移性差。 一般在开发过程中,不使用自定义数据库连接池,而直接使用开源的数据库连接池。

常用的两个开源数据库连接池

  • DBCP(Database Connection Pool)

java数据库连接池的一种,有apache开发,通过数据库连接池,可以让程序自动管理数据库连接的释放和断开。

使用案例

首先需要导入jar包
在这里插入图片描述
JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第11张图片

  • C3P0

开源的JDBC连接池,实现了数据源和JNDI的绑定,支持JDBC3规范和JDBC2的标准扩展。目前使用它的开源项目有Hibenate、Spring等。

使用案列(通过读取配置文件 )
先导包
在这里插入图片描述
然后写配置文件
JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第12张图片
注意配置文件的名字只能时c3p0-config.xml,将这个文件放在src目录下
使用连接池
JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第13张图片
注意:由于c3p0数据库连接池默认用类加载器读取c3p0-config的内容,所以我们不用再用代码读写配置文件的内容。

三. DBUtils

1. 是什么

DBUils是apache组织提供的一个对JDBC进行简单封装的开源工具类,使用它能够简化JDBC应用程序的开发,同时不会影响程序的性能。用来执行数据库增删改查的工作,连接的创建不在范围内

2.基本用法

(1)增删改

首先导包
JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第14张图片
代码如下

JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第15张图片
结果如下

JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第16张图片

(2)查询

用户手动封装

JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第17张图片

用resultSetHandler已经实现的类,不用用户自己手动封装。

JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第18张图片

这里使用了已经实现ResultSetHandler的子类BeanHandler,其中已经封装了将数据存于User中的方法,特别方便。

获取查询的多个元素
JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第19张图片

3.DBUtils的内部原理

(1)增删改

JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第20张图片

(2) 查询

JavaWeb学习笔记 (九)事务 、数据库连接池和DBUtils_第21张图片
其中ResultSetHandler是一个接口,规定了标准,用户可以通过匿名内部类进行数据的封装。

你可能感兴趣的:(javaweb学习笔记)