一、事务的特性和隔离级别(理解)
1、事务的特性:(面试题)
l 原子性:处于同一个事务中的多条语句,要么全都成功,要么全都不成成功。
l 一致性:事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如转账:转账前a+b=2000,转账后a+b=2000
l 隔离性:多线程并发时,一个事务不能被其他事务所干扰。
l 持久性:数据应该被永久性的保存起来。(硬盘,而不是内存)
ACID
2、事务的隔离性专题
如果不考虑事务的隔离性,会导致以下不正确的问题:
a、脏读:指一个事务读到了另外一个事务中未提交的数据
b、不可重复读:指一个事务读到了另外一个事务update后(事务提交了)的数据
c、虚读:指一个事务读到了另外一个事务insert的数据
3、演示操作:
3.1数据库控制隔离级别相关的语句(必须用在事务之中):
数据库有四个隔离级别:
READ UNCOMMITTED:脏读、不可重复读、虚读都有可能发生。
READ COMMITTED:防止脏读发生;不可重复读、虚读都有可能发生。
REPEATABLE READ:(MySQL默认级别)防止脏读、不可重复读;虚读有可能发生。
SERIALIZABLE:防止脏读、不可重复读、虚读的发生
特点:从上到下,隔离级别越高,数据越安全,但是效率越低
select @@tx_isolation; 查看当前数据库的隔离级别
set transaction isolation level 四个级别之一;更改当前事务的隔离级别
^_^回家练习:
---------------------------------------------------
时间 |
T1线程 |
T2线程 |
备注 |
time1 |
set transaction isolation level read uncommitted; start transaction; |
t1线程更改事务的隔离级别为最低级别,并开启了事务 |
|
time2 |
start transaction; |
t1放弃了CPU执行权,t2线程开启了事务 |
|
time3 |
select * from account where name=’aaa’ |
t1查询客户金额为1000 |
|
time4 |
update account set money=money+100 where name=’aaa’ |
t2线程把aaa账户余额加了100块,并没有提交事务 |
|
time5 |
select * from account where name=’aaa’ |
t1获得执行权,重新查询,发现余额为1100(脏读发生了) |
|
time6 |
commit |
t2线程提交了 |
|
time7 |
select * from account where name=’aaa’ |
t1获得执行权,发现余额为1100,读取到了另外线程中提交的数据(发生了不可重复读) |
|
time8 |
commit |
---------------------------------------------------
3.2JDBC中如何控制事务的隔离级别
Connection.
l TRANSACTION_READ_UNCOMMITTED
l TRANSACTION_READ_COMMITTED
l TRANSACTION_REPEATABLE_READ
l TRANSACTION_SERIALIZABLE
改变隔离级别:Connection.setTransactionIsolation(int level)。特别注意,用在开始事务之前。
二、数据库连接池(编码有难度,帮助你理解。尽量理解)
1、自定义连接池
2、对已知类的已知方法(不能改源码),改变它的原有功能(改实现)
目前改写com.mysql.jdbc.Connection.close();让他不要关闭链接,而是还回池中。
l 继承:子类可以覆盖父类的方法(不靠谱)
l 包装(装饰)设计模式
n 口诀:
u 1、编写一个类,实现与被包装类相同的接口
u 2、定义一个变量,记住被包装类对象的引用
u 3、定义构造方法,传入被包装类对象
u 4、对于要改变的方法,书写你的代码即可
u 5、对不需要要改变的方法,用原有对象的
默认适配器设计模式
l 动态代理(很重要。AOP面向切面编程)
总结:(必须知道)
1、日后尽量使用标准的数据源(一般都带有连接池),为的就是提高效率
2、当用户调用Connection.close()方法,并不能关闭链接,而是还回池中
三、开源数据源的配置和使用(实际开发中用的,很简单)
1、DBCP
简介:APache组织实现的。DBCP:DataBase Connection Pool
如何使用:
1.1拷贝jar包到构建路径中
commons-dbcp-1.4.jar和commons-pool-1.5.6.jar
1.2在构建路径中添加一个*.properties的配置文件
#连接设置
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/day19
username=root
password=sorry
#<!-- 初始化连接 -->
initialSize=10
#最大连接数量
maxActive=50
#<!-- 最大空闲连接 -->
maxIdle=20
#<!-- 最小空闲连接 -->
minIdle=5
#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]
#注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=utf8
#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true
#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=
#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=REPEATABLE_READ
1.3编写工具类
2、C3P0
2.1拷贝jar包
c3p0-0.9.1.2.jar
c3p0-0.9.1.2-jdk1.3.jar(可选)
c3p0-oracle-thin-extras-0.9.1.2.jar(Oracle用的)
2.2在类路径中建立一个名称为c3p0-config.xml的配置文件
2.3编写C3P0工具类
3、获取Tomcat管理的数据源
3.1Tomcat在启动时,会按照用户的配置,创建数据源,并把数据源对象绑定到一个名字上(用的是JNDI)。
3.2JNDI:Java Naming and DIrectory Interface (JDK:javax.naming.*)
JNDI就好比window系统的注册表,它是一个Map结构。key是一个由路径和名称组成的字符串,value就是绑定的一个对象。
3.3利用Tomcat管理数据源
a、拷贝数据库驱动jar包到Tomcatlib目录下
b、在应用的META-INF目录下建立一个名称为context.xml的配置文件
c、启动Tomcat,数据源就给你建好了
d、在应用中如何获取数据源
特别注意:不要在main方法中获取数据源,获取不到
四、数据库元数据的获取(写数据库框架用)
1、什么是数据库元数据
元数据:数据库、表、列等定义的信息
2、元数据
数据库的元信息:DatabaseMetaData
获取PreparedStatement占位符的元信息:
结果集元数据信息的获取:ResultSetMetaData