JDBC 学习笔记3
在上次的学习笔记中主要说明了一下JDBC的是如何获取DIRVER的的工作原理,以及简单的介绍了一下六个步骤。今天的笔记主要内容是[JDBC Advanced Topics]异常处理、元数据以及事务。
1、异常 Exception
java.sql.SQLException 对底层数据库异常的封装,它是一个已检查异常。所以应用程序必须对它做处理。
.getErrorCode(); 获取特定于数据库供应商的错误代码。
java.sql.SQLWaring extends SQLExecption 提供关于数据库访问警告信息的异常。
例:
1
try
{
2
//此处省略
3![]()
}
catch
(SQLException e)
{
4![]()
while(e != null)
{
5
e.printStackTrace();
6
e = e.getNextExecption();
7
}
8
}
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
2
3
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
4
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
5
6
7
8
2、元数据:用来描述其他数据的数据
JDBC中的元数据:
ResultSetMetaDate: 结果集元数据,它用来描述结果集本身。
ResultSet.getMetaDate(); 获取当前结果集的元数据。
DatabaseMetaDate: 数据库元数据,用来描述数据库本身。
Connection.getMetaDate(); 获取当前数据库的元数据。
例:
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
3、DML的操作 [JDBC的事务] 以事务为单位
JDBC事务:
定义:一组相关的操作,不可分割,一起成功,一起失败。
相关操作:
Connection:
commit(); JDBC事务提交
rollback(); JDBC事务回滚
JDBC的事务默认情况下是自动提交的,每执行一次SQL命令,就提交commit一次。[AutoCommit]
如:
转帐(){
...
update t_account1 set balance = balance-100;
update t_account2 set balance = balance+100;
...
}
如何让以上两句SQL语句,一起执行,一起失败。所以就需要把他们放在一个事务中。
如:
转帐(){
...
con.setAutoCommit(false);//关闭自动事务提交
update t_account1 set balance = balance-100;
update t_account2 set balance = balance+100;
如果以上两句都成功,则:
con.commit();//提交事务
如果以上任意一个失败,则:
con.rollback();//事务回滚
}
获取主键方式(主键值生成策略)
主键值不应该由UI界面来收集,而应该由应用程序自动生成,常见的策略如下:
a. max(id)方法
select max(id) from table_name;
此方法当有多线程并发时,就会产生问题。
b. sequence 序列
select sequence.nextval from dual;
此方法只适用支持序列的数据库产品,所以不是很通用。
c. 维护单行单列得表
1
create
table
id_table(next_id
number
not
null
);
2
insert
into
id_table next_id
values
(
1
);
3
commit
;
4
--
使用以下SQL自动维护
5
select
next_id
from
id_table
for
update
;
6
update
id_table
set
next_id
=
next_id
+
1
;
7
commit
;
2
3
4
5
6
7
并发控制:多个事务同时操作同一个对象
有三种并发情况,如下:
1、脏读 Dirty reads 读到其他事务没有提交的数据。注:Oracle不支持
2、不可重复读 Repeatable reads 同一个事务在两个不同的时刻读取不同结果
如:
1
T1:
select
score
from
t_score
where
id
=
48
;
2
T2:
update
t_score
set
score
=
score
+
10
where
id
=
48
;
3
T1:
select
score
from
t_score
where
id
=
48
;
解决重复读问题:
2
3
让T1在查询语句中加入for update子句,从而把选定的记录加上排他锁;那么T1事务完成之前,其他事务是不能来获取锁资源的。
3、幻影读 Phanton reads 记录数量变化,而不是行记录的列值
1
T1:elcet
count
(
*
)
from
t_class
where
classname
=
'
******
'
;
2
T2:nsert
into
t_class
values
(![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
.);
3
commit
();
4
T1:selcet
count
(
*
)
from
t_class
where
classname
=
'
******
'
;
5
解决幻影读问题:
2
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
![](http://img.e-com-net.com/image/product/d3c975ab092b4b77b3c90271c80dcc88.gif)
3
4
5
锁表:lock table table_name in mode;
事务隔离级别:SUN在JDBC规范中制定了5个级别,分别用来满足不同的并发性。
Connection:
0 .TRANSACTION_NONE 无
1 .TRANSACTION_READ_UNCOMMITED 可以脏读
2 .TRANSACTION_READ_COMMITED 不可以脏读
4 .TRANSACTION_REPEATABLE 不可以重复读
8 .TRANSACTION_SERIALIZABLE 为每个事务都开辟一个空间
事务的隔离界别设置得越高,则并发性能越差
注:不同数据库,对隔离级别的支持也是不一样的。
如:oracle就不支持0和1两种。
如何设置隔离级别?
如:con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITED);
这个也是默认事务隔离级别。
My Java study notes.